Как использовать пользовательский редактор ячеек 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.");
        }
    }

моя проблема заключается в том, что панель отображается, как я ожидал, я не могу ввести в текстовое поле или изменить установите флажок или нажмите кнопку. пожалуйста, скажите мне, как это решить.

2 ответов


должны добавить правильный LayoutManager, Editable/non_Editable свойства уже видны JPanel

пусть наслаждаются

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());
    }
}

я настоятельно рекомендую повторно использовать функциональность, доступную в рендерерах и редакторах таблиц по умолчанию, так как в вашем коде много ошибок

  1. пожалуйста, разделите редактор, визуализатор и модель таблицы. Иметь их всех в одном классе просто странно
  2. для вашего рендерера не создавайте новые экземпляры Component каждый раз. Вместо этого повторно используйте тот же компонент и просто измените его Component на getTableCellRendererComponent метод
  3. же идет за редактором Component
  4. расширить редактор по умолчанию вместо реализации методов с помощью UnsupportedOperationExceptions или просто возвращая пустой Strings

чтобы поддержать мою четвертую точку, небольшая цитата из Редакторы часть в JTable учебник:

Что делать, если вы хотите указать редактор, отличный от текстового поля, флажка или поля со списком? Поскольку DefaultCellEditor не поддерживает другие типы компонентов, необходимо сделать немного дополнительная работа. Необходимо создать класс, реализующий интерфейс TableCellEditor. Класс AbstractCellEditor-хороший суперкласс для использования. Он реализует суперинтерфейс TableCellEditor, CellEditor, избавляя вас от проблем с реализацией кода запуска событий, необходимого для редакторов ячеек.

ваш класс редактора ячеек должен определить по крайней мере два метода - getCellEditorValue и getTableCellEditorComponent. Метод getCellEditorValue, требуемый CellEditor, возвращает текущее значение ячейки. Метод getTableCellEditorComponent, требуемый TableCellEditor, должен сконфигурировать и вернуть компонент, который вы хотите использовать в качестве редактора.

как четко объяснено, вы должны реализовать код запуска события:

экономя вам проблемы реализации кода запуска событий, необходимого для редакторов ячеек.

что вы явно пренебрегли. Поэтому советую начать с AbstractCellEditor вместо реализация интерфейса с нуля