web-dev-qa-db-ja.com

カスタムJTableセルエディターとセルレンダラーの使用方法

画像で結果を表示するカスタムテーブルレンダーとカスタムセルエディターでJTableを作成しました

enter image description here

JPanelを拡張する別のクラスを使用して、最初の表のセルに示すパネルを作成しました。そして、テーブルの値を

        tbl.setCellEditor(new customCell());
        tbl.getColumnModel().getColumn(0).setCellRenderer(new customCell());

        DefaultTableModel dtm = (DefaultTableModel) tbl.getModel();

        Vector v = new Vector();
        v.add(new Panel());
        v.add("Test");
        dtm.addRow(v);

        v.clear();
        v.add(new Panel());
        v.add("Test 2");
        dtm.addRow(v);

これは、このテーブルを作成するためのテーブルカスタムクラスです。

class customCell extends DefaultTableModel implements TableCellRenderer, TableCellEditor {

        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            Panel p = new Panel();            
            table.setRowHeight(row, p.getHeight());
            return p;
        }

        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {

            return new Panel();
        }

        public Object getCellEditorValue() {
            return "";
        }

        public boolean isCellEditable(EventObject anEvent) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public boolean shouldSelectCell(EventObject anEvent) {
            return true;
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        public boolean stopCellEditing() {
            return true;
        }

        public void cancelCellEditing() {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public void addCellEditorListener(CellEditorListener l) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public void removeCellEditorListener(CellEditorListener l) {
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }

私の問題は、テキストフィールドに入力したり、チェックボックスを変更したり、ボタンをクリックしたりできないので、パネルが表示されると考えられています。これを解決する方法を教えてください。

10
Harsha

すでに表示されているLayoutManagerの適切なJPanelEditable/non_Editableプロパティを追加する必要があります

楽しみましょう

import Java.awt.*;
import Java.awt.event.*;
import Java.util.EventObject;
import javax.swing.*;
import javax.swing.table.*;

public class PanelInTable {

    private JFrame frame;
    private JTable compTable = null;
    private PanelTableModel compModel = null;
    private JButton addButton = null;

    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel("com.Sun.Java.swing.plaf.nimbus.NimbusLookAndFeel");
            //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception fail) {
        }
        SwingUtilities.invokeLater(() -> {
            new PanelInTable().makeUI();
        });
    }

    public void makeUI() {
        compTable = CreateCompTable();
        JScrollPane CompTableScrollpane = new JScrollPane(compTable, 
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        JPanel bottomPanel = CreateBottomPanel();
        frame = new JFrame("Comp Table Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(CompTableScrollpane, BorderLayout.CENTER);
        frame.add(bottomPanel, BorderLayout.SOUTH);
        frame.setPreferredSize(new Dimension(800, 400));
        frame.setLocation(150, 150);
        frame.pack();
        frame.setVisible(true);
    }

    public JTable CreateCompTable() {
        compModel = new PanelTableModel();
        compModel.addRow();
        JTable table = new JTable(compModel);
        table.setRowHeight(new CompCellPanel().getPreferredSize().height);
        table.setTableHeader(null);
        PanelCellEditorRenderer PanelCellEditorRenderer = new PanelCellEditorRenderer();
        table.setDefaultRenderer(Object.class, PanelCellEditorRenderer);
        table.setDefaultEditor(Object.class, PanelCellEditorRenderer);
        return table;
    }

    public JPanel CreateBottomPanel() {
        addButton = new JButton("Add Comp");
        addButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                Object source = ae.getSource();
                if (source == addButton) {
                    compModel.addRow();
                }
            }
        });
        JPanel panel = new JPanel(new GridBagLayout());
        panel.add(addButton);
        return panel;
    }
}

class PanelCellEditorRenderer extends AbstractCellEditor implements 
        TableCellRenderer, TableCellEditor {

    private static final long serialVersionUID = 1L;
    private CompCellPanel renderer = new CompCellPanel();
    private CompCellPanel editor = new CompCellPanel();

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, 
            boolean isSelected, boolean hasFocus, int row, int column) {
        renderer.setComp((Comp) value);
        return renderer;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, 
            boolean isSelected, int row, int column) {
        editor.setComp((Comp) value);
        return editor;
    }

    @Override
    public Object getCellEditorValue() {
        return editor.getComp();
    }

    @Override
    public boolean isCellEditable(EventObject anEvent) {
        return true;
    }

    @Override
    public boolean shouldSelectCell(EventObject anEvent) {
        return false;
    }
}

class PanelTableModel extends DefaultTableModel {

    private static final long serialVersionUID = 1L;

    @Override
    public int getColumnCount() {
        return 1;
    }

    public void addRow() {
        super.addRow(new Object[]{new Comp(0, 0, "", "")});
    }
}

class Comp {

    public int type;
    public int relation;
    public String lower;
    public String upper;

    public Comp(int type, int relation, String lower, String upper) {
        this.type = type;
        this.relation = relation;
        this.lower = lower;
        this.upper = upper;
    }
}

class CompCellPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private JLabel labelWith = new JLabel("With ");
    private JComboBox typeCombo = new JComboBox(new Object[]
    {"height", "length", "volume"});
    private JComboBox relationCombo = new JComboBox(new Object[]
    {"above", "below", "between"});
    private JTextField lowerField = new JTextField();
    private JLabel labelAnd = new JLabel(" and ");
    private JTextField upperField = new JTextField();
    private JButton removeButton = new JButton("remove");

   public CompCellPanel() {
        setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
        relationCombo.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                enableUpper(relationCombo.getSelectedIndex() == 2);
            }
        });
        enableUpper(false);
        removeButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JTable table = (JTable) SwingUtilities.getAncestorOfClass(
                        JTable.class, (Component) e.getSource());
                int row = table.getEditingRow();
                table.getCellEditor().stopCellEditing();
                ((DefaultTableModel) table.getModel()).removeRow(row);
            }
        });
        add(labelWith);
        add(typeCombo);
        add(relationCombo);
        add(lowerField);
        add(labelAnd);
        add(upperField);
        add(Box.createHorizontalStrut(100));
        add(removeButton);
    }

    private void enableUpper(boolean enable) {
        labelAnd.setEnabled(enable);
        upperField.setEnabled(enable);
    }

    public void setComp(Comp Comp) {
        typeCombo.setSelectedIndex(Comp.type);
        relationCombo.setSelectedIndex(Comp.relation);
        lowerField.setText(Comp.lower);
        upperField.setText(Comp.upper);
        enableUpper(Comp.relation == 2);
    }

    public Comp getComp() {
        return new Comp(typeCombo.getSelectedIndex(), 
                relationCombo.getSelectedIndex(), 
                lowerField.getText(), upperField.getText());
    }
}
10
mKorbel

あなたのコードには多くの問題があるので、デフォルトのテーブルレンダラーとエディターで利用可能になった機能を再利用することを強くお勧めします

  1. エディター、レンダラー、テーブルモデルを分割してください。それらすべてを同じクラスに入れるのは奇妙です
  2. レンダラーでは、毎回Componentの新しいインスタンスを作成しないでください。代わりに、同じコンポーネントを再利用し、ComponentメソッドでgetTableCellRendererComponentを変更するだけです。
  3. 同じことがエディタにも当てはまりますComponent
  4. UnsupportedOperationExceptionsを使用して、または空のStringsを返すだけでメソッドを実装する代わりに、デフォルトのエディターを拡張します。

私の4番目のポイントをバックアップするために、 JTableチュートリアルの編集者パート からの小さな引用:

テキストフィールド、チェックボックス、またはコンボボックス以外のエディターを指定する場合はどうでしょうか。 DefaultCellEditorは他のタイプのコンポーネントをサポートしないため、もう少し作業を行う必要があります。 TableCellEditorインターフェースを実装するクラスを作成する必要があります。 AbstractCellEditorクラスは、使用するのに適したスーパークラスです。 TableCellEditorのスーパーインターフェースであるCellEditorを実装しているため、セルエディターに必要なイベント発生コードを実装する手間が省けます。

セルエディタークラスは、少なくとも2つのメソッド(getCellEditorValueおよびgetTableCellEditorComponent)を定義する必要があります。 CellEditorに必要なgetCellEditorValueメソッドは、セルの現在の値を返します。 TableCellEditorに必要なgetTableCellEditorComponentメソッドは、エディターとして使用するコンポーネントを構成して返す必要があります。

そこで明確に説明されているように、イベント発生コードを実装する必要があります。

セルエディタに必要なイベント発生コードを実装する手間を省きます。

あなたが明らかに無視しました。したがって、インターフェイスを最初から実装するのではなく、AbstractCellEditorから始めることをお勧めします

14
Robin