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

我的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

}

...

新代码的问题已解决了更新模型中数据的方式。但是,更新data结构时存在逻辑缺陷。此变量以3行的数组开始。在该actionPerformed()方法newdata中,对只有2个条目的list

的长度执行循环。因此,您仅更新模型的前2行。

似乎您错过了重点。在这里,如何更新模型很重要。该表将显示您的模型拥有的所有数据。如果您仅更新2行,但保留第3行不变,则该表将显示3行(新2行和旧1行)。由于每次都需要更改所有数据,因此需要

。每次都需要重新创建您的数据,而不是表。请参阅更新代码示例。我添加了actionPerformed()使用您当前的源代码重新初始化数据的方法。请阅读内联注释。

以上是 使用JComboBox更改/更新JTable内容(类别) 的全部内容, 来源链接: utcz.com/qa/411050.html

回到顶部