2010-03-30 31 views
9

Cách tốt nhất để thiết lập bảng trong JScrollPane sao cho cột đầu tiên luôn nằm trên màn hình ở cùng vị trí bất kể các cột cuộn ngang và chồng chéo đi qua bên dưới?Làm cách nào để tạo một JTable trong đó cột đầu tiên luôn nằm trong khung nhìn JScrollPane?

Khi thanh cuộn ở xa nhất bên trái, các cột trông bình thường, nhưng khi người dùng cuộn sang phải, cột thứ hai (2 và trên) di chuyển bên dưới cột đầu tiên cho đến cột cuối cùng xuất hiện ở phía ngoài cùng bên phải của viewport?

Tôi tìm thấy một mẫu được lấy từ cuốn sách "Java Swing" của Eckstein, loại này thực hiện điều này, nhưng nó không cho phép thay đổi kích thước của cột đầu tiên. Tôi đã suy nghĩ về một số chương trình mà một JPanel đã tổ chức một cấu trúc ngang và một bảng giữ các cột thứ cấp và một JPanel mà trôi nổi trên chúng (cố định bất kể di chuyển). Cấu trúc sẽ giữ cho hằng số phạm vi khung nhìn như cột đầu tiên được thả nổi xung quanh. Lý tưởng nhất tôi có thể làm điều đó với hai bảng sử dụng cùng một mô hình, nhưng tôi không chắc chắn nếu toàn bộ ý tưởng là một giải pháp ngây thơ. Tôi lý tưởng giống như một thiết lập mà nhiều bảng nằm trên cùng một cuộn dọc, nơi tất cả các cột đầu tiên của chúng được căn chỉnh và di chuyển cùng nhau và chỉ có ít khoảng trống ngang giữa các bảng riêng lẻ.

Trả lời

12

Fixed Column Table thực hiện hầu hết những gì bạn cần.

Nó không hỗ trợ thay đổi kích thước cột cố định, do đó bạn sẽ cần phải thêm mã như:

MouseAdapter ma = new MouseAdapter() 
{ 
    TableColumn column; 
    int columnWidth; 
    int pressedX; 

    public void mousePressed(MouseEvent e) 
    { 
     JTableHeader header = (JTableHeader)e.getComponent(); 
     TableColumnModel tcm = header.getColumnModel(); 
     int columnIndex = tcm.getColumnIndexAtX(e.getX()); 
     Cursor cursor = header.getCursor(); 

     if (columnIndex == tcm.getColumnCount() - 1 
     && cursor == Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)) 
     { 
      column = tcm.getColumn(columnIndex); 
      columnWidth = column.getWidth(); 
      pressedX = e.getX(); 
      header.addMouseMotionListener(this); 
     } 
    } 

    public void mouseReleased(MouseEvent e) 
    { 
     JTableHeader header = (JTableHeader)e.getComponent(); 
     header.removeMouseMotionListener(this); 
    } 

    public void mouseDragged(MouseEvent e) 
    { 
     int width = columnWidth - pressedX + e.getX(); 
     column.setPreferredWidth(width); 
     JTableHeader header = (JTableHeader)e.getComponent(); 
     JTable table = header.getTable(); 
     table.setPreferredScrollableViewportSize(table.getPreferredSize()); 
     JScrollPane scrollPane = (JScrollPane)table.getParent().getParent(); 
     scrollPane.revalidate(); 
    } 
}; 

JTable fixed = fixedColumnTable.getFixedTable(); 
fixed.getTableHeader().addMouseListener(ma); 
+0

Hrmm, tôi mong đợi câu hỏi của tôi là mơ hồ hơn để có được một câu trả lời nhanh chóng. Điều đó sẽ hoạt động rất tốt. Tôi sẽ thử nó với mã cột có thể thay đổi kích thước bạn đã cung cấp. Cảm ơn. – voodoogiant

1

Tôi nghĩ bạn đang đi đúng hướng. Điều bạn có khái niệm là một bảng có 'cột tiêu đề' cho mỗi hàng. Tôi sẽ sử dụng hai bảng - một bảng có cột 'ngoài cùng bên trái' và cái kia có tất cả những cái khác. Sau đó, tôi sẽ trình bày chúng trong một JSplitPane với bảng 'cột ngoài cùng bên trái' bên trái và phần còn lại ở bên phải. Sẽ có một thanh cuộn dọc duy nhất kiểm soát độ lệch y của cả hai bảng và một thanh cuộn ngang duy nhất điều khiển ngăn tay phải (chỉ).

Bạn cũng có thể sử dụng các tính năng nâng cao của JScrollPane để đặt thành phần 'tiêu đề' ở bên trái của vùng cuộn chính. Tôi chưa bao giờ làm điều đó, nhưng bạn có thể sử dụng nó như là 'tiêu đề' của các hàng của bạn.

4

JScrollPane có diện đặc biệt cho điều này, các tiêu đề hàng (xem sơ đồ trong API :)

Tất cả những gì bạn cần làm là: - tạo thêm JTable cho khu vực cố định này - móc nó lên cột đầu tiên của mô hình dữ liệu - đặt nó làm tiêu đề hàng - và bỏ qua bảng chính cột dữ liệu đầu tiên.

Khi cuộn scrollpane cuộn lên và xuống cả hai bảng sẽ cuộn đồng bộ mà không có mã được thêm vào. Khi scrollpane cuộn theo chiều ngang, tiêu đề hàng luôn được hiển thị và chỉ các cuộn bảng chính.

Đối với hầu hết các trường hợp, mã chỉ được thêm vào mà bạn cần là thay đổi kích thước cột, ví dụ như ví dụ của camickr.

2

Kiểm tra lớp học này, được chiết xuất từ ​​http://fahdshariff.blogspot.sg/2010/02/freezing-columns-in-jtable.html

import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JViewport; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.JTableHeader; 
import javax.swing.table.TableModel; 
public class FrozenTablePane extends JScrollPane{  
    public FrozenTablePane(JTable table, int colsToFreeze){  
     super(table);  
     TableModel model = table.getModel();  
     //create a frozen model  
     TableModel frozenModel = new DefaultTableModel(         
       model.getRowCount(),         
       colsToFreeze);  
     //populate the frozen model  
     for (int i = 0; i < model.getRowCount(); i++) {  
      for (int j = 0; j < colsToFreeze; j++) {   
       String value = (String) model.getValueAt(i, j);   
       frozenModel.setValueAt(value, i, j);  
      }  
     } 
    //create frozen table 
    JTable frozenTable = new JTable(frozenModel); 
    //remove the frozen columns from the original table 
    for (int j = 0; j < colsToFreeze; j++) { 
    table.removeColumn(table.getColumnModel().getColumn(0)); 
    }  table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 
    //format the frozen table  
    JTableHeader header = table.getTableHeader();  
    frozenTable.setBackground(header.getBackground());  
    frozenTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);  
    frozenTable.setEnabled(false);  
    //set frozen table as row header view 
    JViewport viewport = new JViewport();  
    viewport.setView(frozenTable); 
    viewport.setPreferredSize(frozenTable.getPreferredSize()); 
    setRowHeaderView(viewport); 
    setCorner(JScrollPane.UPPER_LEFT_CORNER, 
      frozenTable.getTableHeader()); 
    } 
} 

Sau đó, chỉ cần gọi phương thức khởi tạo:

JTable table = new JTable(<yourData>, <yourColumns>); 
FrozenTablePane frozenPane = new FrozenTablePane(table,1);//where 1 is the number of freezed column(s) 
Các vấn đề liên quan