当前位置: 首页 > 面试题库 >

使用JComboBox更改/更新JTable内容(类别)

封景曜
2023-03-14
问题内容

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

但是,您已经在框架中添加了JScrollPane带有的JTable,并且这些继续存在。(如果您尝试调整窗口大小,则会在旧表下方看到新表)。

更新表数据的正确方法是对其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结构时存在逻辑缺陷。此html" target="_blank">变量以3行的数组开始。在该actionPerformed()方法newdata中,对只有2个条目的list
的长度执行循环。因此,您仅更新模型的前2行。

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



 类似资料:
  • 我有这个代码: 当我运行它时,我在控制台上得到以下打印: 因此,它返回415个不受支持的媒体类型错误代码。 我在StackOverflow上发现,它可能是由上下文类型中的charset=UTF-8引起的。所以我的问题是,我如何编辑这个字段来满足我的需求(删除charset=UTF-8)。链接 如何更改该内容类型。由于我不熟悉HTTP协议,请详细说明。

  • 这个问题可能已经得到了回答,我读过很多类似的,但对我不起作用。因此,我的具有扩展的自定义表模型。我的数据是和列名。那么,当我的数据发生更改时,如何更新表呢?我一直在使用,它正在工作,但它将我的自定义单元格呈现器重置为默认值。谢了。

  • 我使用Eclipse创建了一个网站,Servlet在其中将数据发送到jsp。但是我不知道为什么我在Servlet中更改数据。它仍然将旧数据发送到jsp。即使我尝试了这些选项.. 菜单-项目-清理(如果不使用自动构建,请单击此选项) 菜单-项目-项目自动构建(选中此选项) 下面是一个例子: Product.java ProductModel.java ProductController.java i

  • 问题内容: 我正在尝试结合2个jcombobox。1个组合框用于显示费用类别。第二个组合框正在从文本文件读取文件以显示产品类型。如果我更改第一个组合框,我希望第二个组合框将根据用户在第一个组合框中的选择进行更改。 我是否仍有可能从文本文件加载其他组合框?该子项将不是Arrays,而是与以前相同,因为它位于cboperson代码的底部。 编辑的代码: 问题答案: 例如

  • 我是java语言新手,我正在尝试创建一个GUI,它有JComboBox,允许用户选择其中一个选项,并根据所选选项,通过添加更多文本字段来更新面板。目前我面临的一个问题是,如果我选择(选项1),面板不会更新,它应该显示5个文本字段及其标签。 我的问题是:如何更新面板以根据用户从JComboBox中选择的选项添加更多文本字段? 此外,我还面临另一个问题,我无法找到设置JFrame大小的方法 这是我的代

  • 问题内容: 我正在为我的Android手机构建一个小型应用程序,以使用非常基本的REST界面将短信转发到网络服务器。 我正在使用android 4.0.3 SDK。我使用Django和Django restframework包在python中开发了Web服务。设置完全是开箱即用的。基本上有一个端点可以接收包含消息信息(发送者,正文,日期)的JSON对象的POST。我已经使用cURL通过以下命令测试