簡體   English   中英

使用JComboBox更改/更新JTable內容(類別)

[英]Change/Update JTable content with JComboBox(category)

我的JTable有問題。 我的JTable顯示數據庫的內容。 一個數據庫表具有名稱類別。 每個類別都顯示在JComboBox中。 如果單擊類別,則應該更新表內容。

這是我的代碼的簡短摘要,因此可以更輕松地為我提供幫助。 該代碼應可運行:

(TestClass-主要)

package test;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class TestClass implements ActionListener{

    String[] header = {"head", "head", "head"};
    Object[][] data = {{Boolean.FALSE, "text", "text"}, {Boolean.FALSE, "text", "text"}, {Boolean.FALSE, "text", "text"}};

    LinkedList<String> newdata = new LinkedList<String>();

    String[] combolist = {"apple", "banana", "cranberry"};

    JComboBox<String> combobox = new JComboBox<String>(combolist);
    JTable table = new JTable(new TestTableModel(data, header));
    JFrame frame = new JFrame();
    JPanel panel = new JPanel(new GridLayout(1, 0, 1, 0));

    public TestClass() {
        combobox.addActionListener(this);
        panel.add(combobox);

        frame.add(panel, BorderLayout.NORTH);
        frame.add(new JScrollPane(table), BorderLayout.CENTER);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        frame.pack();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == this.combobox) {
            JComboBox<String> combobox = this.combobox;

            newdata.add("Test1");
            newdata.add("Test2");

            TestTableModel model = (TestTableModel) table.getModel();

            int i = 0;
            for (String text : newdata) {
                data[i][0] = Boolean.TRUE;
                data[i][1] = text;
                data[i][2] = text;
                i++;
            }

            model.setData(data);
        }
    }

    public static void main(String[] args) {
        new TestClass();
    }
}

(如果需要,則為TestTableModel-AbstractTableModel(您需要它來執行代碼!)

package test;

import javax.swing.table.AbstractTableModel;

public class TestTableModel extends AbstractTableModel {
    private static final long serialVersionUID = 5044877015250409328L;

    private String[] header;
    private Object[][] data;

    public TestTableModel(Object[][] data, String[] header) {
        this.header = header;
        this.data = data;
    }

    public void setData(Object[][] data) {
        this.data = data;
        fireTableDataChanged();
    }

    @Override
    public Class<?> getColumnClass(int column) {
        if (column == 0) {
            return Boolean.class;
        }
        return super.getColumnClass(column);
    }

    @Override
    public int getColumnCount() {
        return header.length;
    }

    @Override
    public String getColumnName(int column) {
        return header[column];
    }

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

    @Override
    public Object getValueAt(int row, int column) {
        return data[row][column];
    }

    @Override
    public boolean isCellEditable(int row, int column) {
        return column == 0;
    }

    @Override
    public void setValueAt(Object value, int row, int column) {
        data[row][column] = value;
    }

}

使用此短代碼,如果更改類別,表格將凍結。 在我的整個代碼中,它也凍結了,但是當我調整窗口大小時(表調整為與框架相同的大小),我能夠在后台看到更新的Table。 我不知道為什么它不被搶斷。

編輯:更改內容的問題已解決。 源已更新。 但是獲得正確表大小的問題已經解決。 在源代碼中,首先使用3行數組,然后使用2行數組。 我想刪除舊表並創建一個新表,所以行大小正確。

基本上,我只想用新內容更新表。

  • 謝謝你的幫助!

該代碼有錯誤,因為每次調用actionPerformed() ,您都在創建一個新組件:

table = new JTable(new TestTableModel(data, header));
frame.add(new JScrollPane( table ));  // <-- BTW: here you need to put the table otherwise you are adding an empty JScrollPane
frame.validate();

(注意:還有一個錯誤,@ mKorbel提到了)。

但是,您已經在框架中添加了帶有JTableJScrollPane ,並且它們仍然存在。 (如果您嘗試調整窗口大小,則會在舊表下方看到新表)。

更新表數據的正確方法是讓其TableModel進行模型中所需的任何修改,然后根據您所做的更改,觸發適當的fireXXX()方法來通知表重新繪制自身。

作為一個粗略的示例,您的代碼將是:

@Override
public void actionPerformed(ActionEvent e) {
    if (e.getSource() == this.combobox) {
        JComboBox<String> combobox = this.combobox;

        newdata.clear();    // Clear your list or create a new one otherwise data will keep piling up.  
        newdata.add("Test1");
        newdata.add("Test2");

        TestTableModel model = (TestTableModel) table.getModel();

        // Since you need to replace the whole data create a new Object[][] each time
        Object[][] newModelData = new Object[newdata.size()][3];

        // Set whatever data to the new array
        int i = 0;
        for (String text : newdata) {
            newModelData[i][0] = Boolean.TRUE;
            newModelData[i][1] = text;
            newModelData[i][2] = text;
            i++;
        }

        // replace all data of the current model
        model.setData(newModelData);
    }
}
....

// Now inside your table model:
    ...
    @Override
    public Class<?> getColumnClass(int column) {
    // if (column == 0) {   
    //     return Boolean.class;             // <-- this produces a ClassCastException with the data you aretrying to set
    // }
       return super.getColumnClass(column);
    }

    public void setData(Object[][] data) {
        this.data = data;       //  <-- Update the data
        fireTableDataChanged(); //  <-- fire the event so the table is notified. If you change only one cell you need to call the appropriate fire event
    }
    ...

更新1:新代碼的問題已修復了更新模型中數據的方式。 但是,更新data結構時存在邏輯缺陷。 此變量以3行的數組開始。 actionPerformed()方法中,對只有2個條目的newdata列表的長度執行循環。 因此,您僅更新模型的前2行。

更新2:似乎您錯過了重點。 在這里,如何更新模型很重要。 該表將顯示您的模型擁有的所有數據。 如果您僅更新2行,但不更改第3行,則該表將顯示3行(新2行和舊1行)。 由於每次都需要更改所有數據,因此需要完全替換模型中的數據 每次都需要重新創建您的數據,而不是表。 請參閱更新代碼示例。 我添加了actionPerformed()方法,該方法使用您當前的源代碼重新初始化數據。 請閱讀內聯注釋。

更改jtable中的數據后,請嘗試以下代碼。

model.fireTableDataChanged(); table.repaint();

其中model是tablemodel對象,而table是JTable對象

希望對您有所幫助!!!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM