我创建了一个扩展DefaultTableModel的类MyTableModel。我想要的是,已经用数据初始化了三列。在MyTableModel的构造函数内部,我通过调用this.addColumn("FIRST COL", FIRST_COL_VALUES);
来设置头/数据值,但是我得到了这个异常“线程中的异常”main“java.lang.ArrayIndexOutOfBoundsException:0> = 0”,我该如何解决这个问题? / p>
public MyTableModel () {
// code below is what I tried so far to fix the exception
//super(INPUT_ROW_COUNT, 1);
// next three lines, is from what I expect to work, but instead I get exception
//this.addColumn("First Column", FIRST_COL_VALUES);
//this.addColumn("Second Column", SECOND_COL_VALUES);
//this.addColumn("Third Column", THIRD_COL_VALUES);
//TableColumn column = new TableColumn();
//column.setModelIndex(0);
//column.setHeaderValue("String value");
//this.addColumn(column);
}
更新
public class Main {
public Main() {
Model model = new Model();
Model.TTableModel tableModel = model.new TTableModel();
Model.TComboBoxModel cBoxModel = model.new TComboBoxModel();
View view = new View(tableModel, cBoxModel);
new Controller(view, model, tableModel, cBoxModel);
}
public static void main(String[] args) {
new Main();
}
}
import java.util.ArrayList;
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import javax.swing.table.DefaultTableModel;
public class Model {
private static final int ROW_COUNT = 8;
private ArrayList<Object> columnsNames = new ArrayList<>();
private Object[][] data = new Object[ROW_COUNT][0];
private int columnIndex;
public int getColumnIndex() {
return columnIndex;
}
public void increaseColumnIndex() {
columnIndex++;
}
public void decreaseColumnIndex() {
columnIndex--;
}
public void displayArrayListObjects() {
System.out.println(columnsNames);
}
class TTableModel extends DefaultTableModel {
public TTableModel() {
//super(new Object[][]{{1, 2, 3, 4, 5, 6, 7, 8}, {4, 5, 6, 7}},new String[]{"First", "Second", "Third"});
this.addColumn("First", new Object[] {1, 2, 3, 4, 5, 6, 7, 8});
this.addColumn("Second", new Object[] {1, 2, 3, 4, 5, 6, 7, 8});
this.addColumn("Third", new Object[] {1, 2, 3, 4, 5, 6, 7, 8});
}
public void addColumn(String header) {
columnsNames.add(header);
fireTableStructureChanged();
}
public void removeColumn() {
if (columnIndex >= 0 && columnIndex < getColumnCount()) {
columnsNames.remove(columnIndex);
fireTableStructureChanged();
}
}
@Override
public int getColumnCount() {
return columnsNames.size();
}
@Override
public String getColumnName(int column) {
return columnsNames.get(column).toString();
}
@Override
public int getRowCount() {
if (data != null) {
return data.length;
}
return 0;
}
@Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
}
class TComboBoxModel extends AbstractListModel implements ComboBoxModel {
private Object selectedItem = null;
private ArrayList<Object> itemList = new ArrayList<>();
public void addItem(String item) {
this.itemList.add(item);
this.fireIntervalAdded(item, columnIndex, columnIndex);
}
public void removeItem() {
if (columnIndex >= 0 && columnIndex < getSize()) {
this.itemList.remove(columnIndex);
this.fireIntervalRemoved(selectedItem, columnIndex, columnIndex);
}
}
public void updateSelectedItem() {
if (itemList.get(0) != null) {
selectedItem = itemList.get(0);
} else {
if (selectedItem != null) {
selectedItem = null;
this.fireContentsChanged(selectedItem, -1, -1);
}
}
}
@Override
public void setSelectedItem(Object anObject) {
if ((selectedItem != null && !selectedItem.equals(anObject)) || selectedItem == null && anObject != null) {
this.selectedItem = anObject;
this.fireContentsChanged(anObject, -1, -1);
}
}
@Override
public Object getSelectedItem() {
return selectedItem;
}
@Override
public int getSize() {
return columnsNames.size();
}
@Override
public Object getElementAt(int index) {
return columnsNames.get(index).toString();
}
}
}
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import mvc1.Model.TComboBoxModel;
import mvc1.Model.TTableModel;
public class Controller {
private View view;
private Model model;
private Model.TTableModel tableModel;
private Model.TComboBoxModel cBoxModel;
public Controller(View view, Model model, TTableModel tableModel, TComboBoxModel cBoxModel) {
this.view = view;
this.model = model;
this.tableModel = tableModel;
this.cBoxModel = cBoxModel;
this.view.addButtonListener(new ButtonActionListener());
}
class ButtonActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String s = e.getActionCommand();
switch (s) {
case "Add New Column":
model.increaseColumnIndex();
tableModel.addColumn("Field " + model.getColumnIndex());
break;
case "Remove Column":
if (model.getColumnIndex() != 0) {
model.decreaseColumnIndex();
tableModel.removeColumn();
} else {
view.displayErrorMessage("There is no column left to remove.");
}
break;
case "Calculate Column":
model.displayArrayListObjects();
break;
case "Final Results Of All Rows":
break;
}
}
}
}
import java.awt.BorderLayout;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.TableModel;
public class View {
private JMenuBar menuBar;
private JMenu menuFile;
private JMenuItem newMenuItem;
private JMenuItem exitMenuItem;
private JMenu menuView;
private JMenuItem aboutMenuItem;
private JButton addNewColumnButton;
private JButton removeColumnButton;
private JButton calculateColumnButton;
private JButton totalResultButton;
private JLabel textLabel;
private JTextField columnField;
private JTextField finalResultField;
private JComboBox columnListCB;
private JTable table;
public View(TableModel tableModel, ComboBoxModel cBoxModel) {
JFrame frame = new JFrame("MVC");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setJMenuBar(getMenuBarComponent());
frame.add(getPanelComponents(tableModel, cBoxModel));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
void addMenuListener(ActionListener l) {
newMenuItem.addActionListener(l);
aboutMenuItem.addActionListener(l);
exitMenuItem.addActionListener(l);
}
void addButtonListener(ActionListener l) {
addNewColumnButton.addActionListener(l);
removeColumnButton.addActionListener(l);
calculateColumnButton.addActionListener(l);
totalResultButton.addActionListener(l);
}
void displayErrorMessage(String errorMessage) {
JOptionPane.showMessageDialog(null, errorMessage, "Error Message", JOptionPane.ERROR_MESSAGE);
}
void displayInfoMessage(String infoMessage) {
JOptionPane.showMessageDialog(null, infoMessage, "Information Message", JOptionPane.INFORMATION_MESSAGE);
}
private JMenuBar getMenuBarComponent() {
menuBar = new JMenuBar();
menuFile = new JMenu("File");
newMenuItem = new JMenuItem("New");
menuFile.add(newMenuItem);
menuFile.addSeparator();
exitMenuItem = new JMenuItem("Exit");
menuFile.add(exitMenuItem);
menuView = new JMenu("View");
aboutMenuItem = new JMenuItem("About Me");
menuView.add(aboutMenuItem);
menuBar.add(menuFile);
menuBar.add(menuView);
return menuBar;
}
private JPanel getPanelComponents(TableModel tableModel, ComboBoxModel cBoxModel) {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panel.add(centerPanel(tableModel), BorderLayout.CENTER);
panel.add(southPanel(), BorderLayout.SOUTH);
panel.add(eastPanel(cBoxModel), BorderLayout.EAST);
return panel;
}
private JPanel centerPanel(TableModel tableModel) {
JPanel centerPanel = new JPanel(new GridLayout());
table = new JTable(tableModel);
table.setPreferredScrollableViewportSize(new Dimension(450, 150));
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
centerPanel.add(new JScrollPane(table));
return centerPanel;
}
private JPanel southPanel() {
JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5));
totalResultButton = new JButton("Final Results Of All Rows");
southPanel.add(totalResultButton);
textLabel = new JLabel("Total result:");
southPanel.add(textLabel);
finalResultField = new JTextField();
finalResultField.setPreferredSize(new Dimension(50, 25));
southPanel.add(finalResultField);
return southPanel;
}
private JPanel eastPanel(ComboBoxModel cBoxModel) {
JPanel eastPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
Box eastPanelBox = Box.createVerticalBox();
addNewColumnButton = new JButton("Add New Column");
addNewColumnButton.setAlignmentX(Box.CENTER_ALIGNMENT);
eastPanelBox.add(addNewColumnButton);
eastPanelBox.add(Box.createVerticalStrut(5));
removeColumnButton = new JButton("Remove Column");
removeColumnButton.setAlignmentX(Box.CENTER_ALIGNMENT);
eastPanelBox.add(removeColumnButton);
eastPanelBox.add(Box.createVerticalStrut(5));
columnField = new JTextField();
columnField.setAlignmentX(Box.CENTER_ALIGNMENT);
columnField.setPreferredSize(new Dimension(130, 25));
eastPanelBox.add(columnField);
eastPanelBox.add(Box.createVerticalStrut(5));
columnListCB = new JComboBox(cBoxModel);
columnListCB.setAlignmentX(Box.CENTER_ALIGNMENT);
eastPanelBox.add(columnListCB); // might need to remove
eastPanelBox.add(Box.createVerticalStrut(5));
calculateColumnButton = new JButton("Calculate Column");
calculateColumnButton.setAlignmentX(Box.CENTER_ALIGNMENT);
eastPanelBox.add(calculateColumnButton);
eastPanel.add(eastPanelBox);
return eastPanel;
}
}
答案 0 :(得分:3)
我创建了一个扩展DefaultTableModel的类MyTableModel。和 我想要的是,已经用数据初始化了三列。 在MyTableModel的构造函数内部,我设置了标头/数据值 调用this.addColumn(“FIRST COL”,FIRST_COL_VALUES);但我明白了 异常“线程中的异常”主“ java.lang.ArrayIndexOutOfBoundsException:0&gt; = 0“,我该如何解决这个问题?
这可以通过覆盖TableColumn
来实现有(非常有用的方法,如果不使用则删除)
TableColumn column = new TableColumn();
column.setCellRenderer(....);
column.setModelIndex(int);
column.setHeaderValue("String value");
column.setPreferredWidth(int);
columnModel.addColumn(column);
column = new TableColumn();
column.setCellRenderer(....);
column.setModelIndex(int);
column.setHeaderValue("String value");
column.setPreferredWidth(int);
columnModel.addColumn(column);
column = new TableColumn();
column.setCellRenderer(....);
column.setModelIndex(int);
column.setHeaderValue("String value");
column.setPreferredWidth(int);
columnModel.addColumn(column);
table.setColumnModel(columnModel);
编辑,您可以从@MadProgrammer提供SCCCE开始,然后仅为未来的读者提供
import java.awt.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
public class CheckBoxTable extends JPanel {
public static final String[] COLUMNS = {"Purchased", "Item"};
public static final String[] INITIAL_ITEMS = {"Milk", "Flour", "Rice", "Cooking Oil", "Vinegar"};
private static final long serialVersionUID = 1L;
private CheckBoxDefaultTableModel model = new CheckBoxDefaultTableModel(COLUMNS, 0, 0);
private JTable table = new JTable(model);
public CheckBoxTable() {
setLayout(new BorderLayout(5, 5));
add(new JScrollPane(table), BorderLayout.CENTER);
for (int i = 0; i < INITIAL_ITEMS.length; i++) {
Object[] row = {Boolean.FALSE, INITIAL_ITEMS[i]};
model.addRow(row);
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("CheckBoxTable");
frame.getContentPane().add(new CheckBoxTable());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowUI();
}
});
}
}
class CheckBoxDefaultTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
private int checkColumn;
CheckBoxDefaultTableModel(Object[] columnNames, int rowCount, int checkColumn) {
super(columnNames, rowCount);
this.checkColumn = checkColumn;
}
@Override
public Class<?> getColumnClass(int columnNumber) {
if (columnNumber == checkColumn) {
return Boolean.class;
}
return super.getColumnClass(columnNumber);
}
}
答案 1 :(得分:2)
您没有提供任何代码,因此我只能猜测您的FIRST_COL_VALUES
等未初始化(可能是无效长度?),或者您可能正在替换代码中其他位置的模型。使用数据显示3列非常简单,如下所示。
请注意,这是一个可运行的示例。如果您为代码提供类似的代码,我将能够更详细地解释您的错误实际上是什么。
package gui.table;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class ThreeColumnDemo {
public static class ThreeColumnModel extends DefaultTableModel {
public ThreeColumnModel() {
// Initialize with 3 rows 0 columns
super(3, 0);
// add columns with data for each row
this.addColumn("First Column", new String[] {"Value1_1", "Value2_1", "Value3_1" });
this.addColumn("Second Column", new String[] {"Value1_2", "Value2_2", "Value3_2" });
this.addColumn("Third Column", new String[] {"Value1_3", "Value2_3", "Value3_3" });
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
JFrame window = new JFrame("3-column demo");
window.setPreferredSize(new Dimension(600, 400));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTable table = new JTable( new ThreeColumnModel() );
// put the table in a scroll pane so column headers are visible
window.add(new JScrollPane(table));
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
});
}
}
更新1:您未正确扩展DefaultTableModel
。当您在构造函数中调用addColumn(...)
时,父级会插入一个新列名称,当它尝试为行/列腾出空间时,它会调用您重写的方法,例如getColumnCount()
,getColumnName()
等。但是,您的模型不使用父项的基础数据,而是检查此时为空的新结构(ArrayList
)。因此父对象遇到不存在的行为(即它只添加了一个新列,getColumnCount()
返回0
)。只需注释掉以下方法,您的代码就可以运行:getColumnCount()
,getColumnName()
,getRowCount()
,getValueAt()
。
然后你应该决定你想做什么。 DefaultTableModel
具有存储数据的数据结构。如果扩展它,请使用这些结构,并且不要覆盖与父进行相同行为的方法,只是为了摇动它。如果要添加一些附加行为,则应扩展它。
另一方面,如果您想使用自己的数据结构和自己的方式添加/删除列和行,则只需扩展AbstractTableModel
。
更新2:关于AbstractTableModel
和您的问题:模型就是它的名字所说的。一种建模数据的方法。当您使用Object[]
或数组数组或ArrayList<Object>
时,您会执行相同的操作。这是一个模型,但相当差。表模型封装了一个抽象的数据结构,无论多么复杂(即JTree
使用它来封装树节点的层次结构),它都可以满足您的需求。
所有Swing组件的行为方式相同:更新模型并使用事件(通常调用fireXXX()
)通知相应的组件重绘自己。
因此,在您的情况下,如果您需要添加/删除列,那么您应该有一个方法addColumn/removeColumn
,可以在外部调用,即在创建表之后。该模型将在内部更新其数据并调用适当的fireXXX
方法。关于您应该使用哪种数据类型,请使用更方便的方法。在您的示例中,您使用Integer
作为数据类型,因此Object[]
或Integer[]
或相应的ArrayList
有意义。如果您使用更复杂的数据类型,您甚至可以引入一个新的Column
类来封装数据。它可能会像您需要的那样复杂。
答案 2 :(得分:0)
在MyTableModel
构造函数中,尝试先调用此行:
super(ROW_COUNT, COLUMN_COUNT);
其中ROW_COUNT
和COLUMN_COUNT
分别是表格中的行数和列数。