0

DefaultTableModel を拡張するクラス MyTableModel を作成しました。そして、私が望むのは、すでに 3 つの列をデータで初期化していることです。MyTableModel のコンストラクター内で呼び出してヘッダー/データ値を設定しましthis.addColumn("FIRST COL", FIRST_COL_VALUES);たが、「スレッド "main" java.lang.ArrayIndexOutOfBoundsException での例外: 0 >= 0」という例外が発生しました。これを修正するにはどうすればよいですか?

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;
    }
}
4

3 に答える 3

3

DefaultTableModel を拡張するクラス MyTableModel を作成しました。そして、私が望むのは、すでに 3 つの列をデータで初期化していることです。MyTableModel のコンストラクター内で、 this.addColumn("FIRST COL", FIRST_COL_VALUES); を呼び出してヘッダー/データ値を設定します。しかし、「スレッド「メイン」での例外 java.lang.ArrayIndexOutOfBoundsException: 0 >= 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);

EDIT、@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);
    }
}
于 2013-08-18T21:44:16.370 に答える
2

FIRST_COL_VALUESあなたはコードを提供していないので、あなたのetcが初期化されていない(おそらく無効な長さですか?)か、コードのどこかでモデルを置き換えていると推測できます。以下に示すように、データを含む 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、データをカプセル化する新しいクラスを導入することもできます。必要に応じて複雑になる可能性があります。

于 2013-08-19T10:00:36.773 に答える
0

コンストラクター内で、MyTableModel何よりも先に次の行を呼び出してみてください。

super(ROW_COUNT, COLUMN_COUNT);

ここでROW_COUNT、 とCOLUMN_COUNTは、それぞれテーブル内の行と列の数です。

于 2013-08-18T21:32:57.247 に答える