2011-10-31 19 views
8

Trong ứng dụng của tôi, tôi đã sử dụng bảng java tương tự ví dụ this. Vấn đề của tôi là khi tôi thay đổi một giá trị của một ô (ngay cả trong ví dụ trên) mô hình dữ liệu không được cập nhật cho đến khi tôi bấm vào một ô khác. Ngay cả khi tôi nhấp vào vùng màu xám bên dưới bảng sau khi thay đổi giá trị ô thì mô hình sẽ không thay đổi. Tôi nghĩ rằng lý do là tế bào ở lại tập trung cho đến khi tôi bấm vào một tế bào khác nhau. Làm cách nào để tránh điều này và cập nhật mô hình mà không cần nhấp vào ô bảng. Cảm ơn trướcCập nhật ô JTable không hoạt động

Tôi có chỉnh sửa các mẫu mã trên để phản ánh các vấn đề

public class JTableDemo extends JApplet { 
    private JTextArea txt = new JTextArea(4, 20); 

    // The TableModel controls all the data: 
    class DataModel extends AbstractTableModel { 
    Object[][] data = { { "one", "two", "three", "four" }, 
     { "five", "six", "seven", "eight" }, 
     { "nine", "ten", "eleven", "twelve" }, }; 

    // Prints data when table changes: 
    class TML implements TableModelListener { 
     public void tableChanged(TableModelEvent e) { 
     txt.setText(""); // Clear it 
     for (int i = 0; i < data.length; i++) { 
      for (int j = 0; j < data[0].length; j++) 
      txt.append(data[i][j] + " "); 
      txt.append("\n"); 
     } 
     } 
    } 

    public DataModel() { 
     addTableModelListener(new TML()); 
     fireTableDataChanged(); 
    } 

    public int getColumnCount() { 
     return data[0].length; 
    } 

    public int getRowCount() { 
     return data.length; 
    } 

    public Object getValueAt(int row, int col) { 
     return data[row][col]; 
    } 

    public void setValueAt(Object val, int row, int col) { 
     data[row][col] = val; 
     System.out.println(val); 
     // Indicate the change has happened: 
     fireTableDataChanged(); 
    } 

    public boolean isCellEditable(int row, int col) { 
     return true; 
    } 
    } 

    public void init() { 
    Container cp = getContentPane(); 
    JTable table = new JTable(new DataModel()); 
    cp.add(new JScrollPane(table)); 
    cp.add(BorderLayout.SOUTH, txt); 
    } 

    public static void main(String[] args) { 
    run(new JTableDemo(), 350, 200); 
    } 

    public static void run(JApplet applet, int width, int height) { 
    JFrame frame = new JFrame(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.getContentPane().add(applet); 
    frame.setSize(width, height); 
    applet.init(); 
    applet.start(); 
    frame.setVisible(true); 
    } 
} 

Khi bạn chạy ví dụ bạn có thể xem nội dung bảng trong vùng văn bản bên dưới bảng. Sau khi bạn cập nhật một ô, nó sẽ xuất hiện trong hộp văn bản bên dưới. Nhưng phương thức 'setValueAt' sẽ không gọi cho đến khi bạn nhấp vào một ô khác.

+1

Bạn có thể chỉnh sửa câu hỏi của mình và thêm [SSCCE] (http://sscce.org) để hiển thị sự cố không? –

+0

giống như SSCCE +1 – mKorbel

Trả lời

8

Cơ chế cập nhật mặc định chỉ thay đổi mô hình khi trình chỉnh sửa ô bị mất tiêu điểm. Hoặc là tabbing ra khỏi tế bào hoặc nhấp vào trong một tế bào khác nhau sẽ gây ra sự kiện "tập trung bị mất" quan trọng mà gây ra sự thay đổi mô hình.

Nhấp vào vùng màu xám sẽ không có hiệu lực vì không có yếu tố hoạt động nào có thể xử lý sự kiện - bảng bỏ qua nhấp chuột.

Nếu bạn muốn thay đổi điều này, bạn cần tìm một sự kiện cho máy tính biết rằng người dùng "được thực hiện với chỉnh sửa". Làm sao bạn biết điều đó?

  • Bạn có thể thêm ActionListener (xem http://download.oracle.com/javase/tutorial/uiswing/components/textfield.html). Nó sẽ được kích hoạt khi bạn nhấn RETURN. Trong trình xử lý, hãy gọi fireEditingStopped() để kích hoạt mã "sao chép sang mô hình" (xem http://download.oracle.com/javase/tutorial/uiswing/components/table.html#editor).
  • Bạn có thể thêm một nút "Save" bên dưới bảng và gọi mã này trong nó ActionListner:

    if(null != jTable.getCellEditor()) { 
        // there is an edit in progress 
        jTable.getCellEditor().stopCellEditing() 
    } 
    
  • Bạn có thể cập nhật các mô hình cho mỗi phím nhấn bằng cách thêm một handler bấm phím nhưng điều đó có thể gây ra các trình soạn thảo để biến mất.

[EDIT] Lưu ý rằng việc thêm một nút "Save" có thể phá vỡ chỉnh sửa "dòng chảy" của người sử dụng (bấm ô trong bảng, chỉnh sửa, lấy chuột, nhằm mục đích, nhấp vào lưu, bấm vào ô tiếp theo, quay trở lại bàn phím, chỉnh sửa, ...)

+0

Tôi làm cách nào để sử dụng nút Lưu vào đó. Tôi cảm thấy nó có thể làm việc cho tôi .. – nath

+0

Chỉ cần thêm một nút mà không có gì với một nhãn "Lưu".Cùng với tài sản của khách hàng từ câu trả lời của kleopatra, điều đó cần phải thực hiện. Lưu ý rằng nó sẽ làm phiền người dùng của bạn bởi vì nó có nghĩa là một nhấp chuột bổ sung. Hãy thử thêm một bản ghi nhớ để mọi người có thể ngừng chỉnh sửa bằng "Alt + S" (mà không cần rời khỏi bàn phím). –

+1

no: a focusLost theo mặc định _does not_ kích hoạt một cam kết (đó là một vấn đề lâu dài cho các lứa tuổi, cho đến khi THEY có thể được thuyết phục để hỗ trợ ít nhất để tùy chọn thiết lập hành vi đó). Trong thực tế, cam kết trên tabbing hoặc nhấp vào một ô khác được kích hoạt rõ ràng bằng mã TableUI – kleopatra

12

Hành vi được mong đợi: giá trị được chỉnh sửa không được cam kết với mô hình sao lưu cho đến khi cử chỉ người dùng rõ ràng, như f.i. nhấn enter hoặc tabbing out hoặc nhấp vào vị trí khác trong bảng ...

Một điều kỳ quặc (một số gọi là lỗi :-) của JTable là việc chỉnh sửa không được mặc định chấm dứt khi chuyển tiêu điểm sang "bên ngoài" của bảng . Để buộc nó làm như vậy, bạn cần phải cấu hình nó thích:

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 

BTW (không liên quan, chỉ dành riêng cho sự tỉnh táo): luôn luôn bắn loại sự kiện hạt mịn nhất, ở đây là sẽ là một cellUpdated thay cho búa dataChanged .

+0

Tôi yêu câu trả lời thứ hai, tuyệt vời và có giá trị của bạn +1 – mKorbel