使用JComboBox更改/更新JTable内容(类别) [英] Change/Update JTable content with JComboBox(category)

查看:132
本文介绍了使用JComboBox更改/更新JTable内容(类别)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的JTable有问题。我的JTable显示数据库的内容。一个数据库表具有名称类别。每个类别都显示在JComboBox中。如果我单击类别,则应该更新表的内容。

I have a problem with my JTable. My JTable displays content of a database. One database table has the name category. Every category is displayed in the JComboBox. If I click on a category it should update the table content.

此处为您提供了一段简短的代码摘要,因此可以更轻松地为我提供帮助。该代码应该是可运行的:

Here is a short snipped of my code for you, so it is easier to help me. The code should be runable:

(TestClass-Main)

(TestClass - Main)

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,如果需要(您需要执行代码!))

(TestTableModel - AbstractTableModel if required (you need it to execute the code!))

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。我不知道为什么它不会被剪掉。

With this short code the table freeze if you change the category. At my whole code,t it freeze too, but I am able to see the updated Table in the background when I resize the window (table resize to the same size as the frame). I don't know why it isn't at the snipped.

编辑:
更改内容的问题已解决。源已更新。但是获得正确表大小的问题已经解决。在源代码中,首先使用3行数组,然后使用2行数组。我想删除旧表并创建一个新表,所以行大小正确。

The problem to change the content has been solved. The source has been updated. But the problem to get the right table size hasent been solved yet. In the source first I use a 3 row array and after that a 2 row array. I want to delete the old table and create a new one, so the row size is right.

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

Basically I just want to update the table with new content.


  • 感谢您的帮助!

推荐答案

该代码有错误,因为每次调用 actionPerformed()时,您正在创建一个新组件:

The code is buggy because every time actionPerformed() is called, you are creating a new component:

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提到了)。

(Note: There is an additional bug, @mKorbel mentioned it).

不过,您已经在框架中添加了 JScrollPane JTable 继续存在。 (如果您尝试调整窗口大小,则会在旧表下方看到新表。)

However you have already added a JScrollPane with a JTable to the frame and those continue to exist. (if you try to resize the window you will see the new table beneath the old one).

更新表数据的正确方法是获取其 TableModel 进行模型中所需的任何修改 ,然后根据您所做的更改,触发适当的 fireXXX()

The correct way to update the table data is to get its TableModel make any modifications required in the model and then depending on what you changed you will fire the apporpriate fireXXX() method to notify the table to redraw itself.

作为一个粗略的例子,您的代码将是:

As a crude example your code would be:

@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()方法中,对长度为 newdata 的列表执行循环,该列表只有2个条目。因此,您仅更新模型的前2行。

Update 1: Your problem with your new code has fixed the way that you update the data in the model. However you have a logical flaw when you update the data structure. This variable starts as an array of 3 rows. In the actionPerformed() method you perform a loop for the length of newdata list which only has 2 entries. So you update only the first 2 rows of your model.

更新2:似乎您错过了重点。在这里,如何更新模型很重要。该表将显示您的模型拥有的所有数据。如果您仅更新2行,但不更改第3行,则该表将显示3行(新2行和旧1行)。由于每次都需要更改所有数据,因此您需要完全替换模型中的数据。每次都需要重新创建您的数据,而不是表。请参阅更新代码示例。我添加了 actionPerformed()方法,该方法使用您当前的源代码重新初始化数据。请阅读内联注释。

Update 2: It seems that you are missing the point. How you update your model matters here. The table will display whatever data your model has. If you only update 2 rows but leave the 3rd one unmodified then the table will display 3 rows (2 new ones and an old one). Since you need to change each time all the data then you need to completely replace the data in the model. It is your data that need to be re-created each time not the table. See the update code example. I have added the actionPerformed() method that re-initializes the data with your current source code. Please read the inline comments.

这篇关于使用JComboBox更改/更新JTable内容(类别)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆