【问题标题】:Linking renderer that displays a jComboBox to a cell in the jTable将显示 jComboBox 的渲染器链接到 jTable 中的单元格
【发布时间】:2013-07-18 22:51:10
【问题描述】:

问题是,当用户单击具有线条样式的单元格并选择 4 个选项之一,然后单击具有线条样式的其他单元格之后,其他单元格显示线条样式,在先前选定的单元格中选择.如何使“线条样式”列中每个单元格(不同单元格中的不同线条样式)的线条样式唯一? “线条颜色”列中的单元格可以正常工作,并且它们的实现方式类似。

这里是 SSCCE:

主类:

import javax.swing.JFrame;

public class PanelMain {
    public static void main(String[] args) {
        String[] tab = { "abc", "cde", "efg" };
        Panel panel = new Panel(tab);
        JFrame frame = new JFrame();
        frame.add(panel);
        frame.setVisible(true);
    }
}

面板:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

@SuppressWarnings("serial")
public class Panel extends JPanel {

    private JScrollPane scrollPane_properties;
    private JTable table_properties;
    private Object[][] dataToTable;

    public Panel(String[] tab) {
        setPreferredSize(new Dimension(293, 416));
        setLayout(null);

        scrollPane_properties = new JScrollPane();
        scrollPane_properties.setBounds(10, 11, 273, 393);
        add(scrollPane_properties);

        dataToTable = new Object[tab.length][3];

        for (int i = 0; i < tab.length; i++) {
            dataToTable[i][0] = tab[i];
            dataToTable[i][1] = LineStyle.values()[0].getStroke();
            dataToTable[i][2] = ColorGenerator.generateColor();
        }

        table_properties = new JTable(new MyTableModel());
        table_properties.setAutoCreateRowSorter(true);

        table_properties.setDefaultRenderer(Color.class, new TableCellColorRenderer(true));
        table_properties.setDefaultEditor(Color.class, new TableCellColorEditor());

        table_properties.setDefaultRenderer(BasicStroke.class, new TableCellLineRenderer(true));
        table_properties.setDefaultEditor(BasicStroke.class, new TableCellLineEditor());

        scrollPane_properties.setViewportView(table_properties);
    }

    class MyTableModel extends AbstractTableModel {
        private String[] columnNames = { "Name", "LineStyle", "LineColor" };
        private Object[][] data = dataToTable;

        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return data.length;
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            return data[row][col];
        }

        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }

        public boolean isCellEditable(int row, int col) {
            if (col < 1) {
                return false;
            } else {
                return true;
            }
        }

        public void setValueAt(Object value, int row, int col) {
            data[row][col] = value;
            fireTableCellUpdated(row, col);
        }
    }

}

TableCellColorEditor:

import javax.swing.AbstractCellEditor;
import javax.swing.table.TableCellEditor;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JTable;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TableCellColorEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
    Color currentColor;
    JButton button;
    JColorChooser colorChooser;
    JDialog dialog;
    protected static final String EDIT = "edit";

    public TableCellColorEditor() {
        button = new JButton();
        button.setActionCommand(EDIT);
        button.addActionListener(this);
        button.setBorderPainted(false);

        colorChooser = new JColorChooser();
        dialog = JColorChooser.createDialog(button, "Pick a Color", true, colorChooser, this, null);
    }

    public void actionPerformed(ActionEvent e) {
        if (EDIT.equals(e.getActionCommand())) {

            button.setBackground(currentColor);
            colorChooser.setColor(currentColor);
            dialog.setVisible(true);

            fireEditingStopped();

        } else {
            currentColor = colorChooser.getColor();
        }
    }

    public Object getCellEditorValue() {
        return currentColor;
    }

    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        currentColor = (Color) value;
        return button;
    }
}

TableCellColorRenderer:

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.border.Border;
import javax.swing.table.TableCellRenderer;
import java.awt.Color;
import java.awt.Component;

public class TableCellColorRenderer extends JLabel implements TableCellRenderer {
    Border unselectedBorder = null;
    Border selectedBorder = null;
    boolean isBordered = true;

    public TableCellColorRenderer(boolean isBordered) {
        this.isBordered = isBordered;
        setOpaque(true);
    }

    public Component getTableCellRendererComponent(JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) {
        Color newColor = (Color) color;
        setBackground(newColor);
        if (isBordered) {
            if (isSelected) {
                if (selectedBorder == null) {
                    selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getSelectionBackground());
                }
                setBorder(selectedBorder);
            } else {
                if (unselectedBorder == null) {
                    unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5, table.getBackground());
                }
                setBorder(unselectedBorder);
            }
        }

        setToolTipText("RGB value: " + newColor.getRed() + ", " + newColor.getGreen() + ", " + newColor.getBlue());
        return this;
    }
}

TableCellLineEditor:

import java.awt.BasicStroke;
import java.awt.Component;

import javax.swing.AbstractCellEditor;
import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;

public class TableCellLineEditor extends AbstractCellEditor implements TableCellEditor {

    JComboBox combobox;

    public TableCellLineEditor() {

        combobox = new JComboBox(LineStyle.values());
        combobox.setRenderer(new ListCellLineRenderer());
    }

    @Override
    public Object getCellEditorValue() {
        return (BasicStroke) LineStyle.values()[combobox.getSelectedIndex()].getStroke();
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        BasicStroke stroke = (BasicStroke) LineStyle.values()[combobox.getSelectedIndex()].getStroke();
        return combobox;
    }

}

TableCellLineRenderer:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

public class TableCellLineRenderer extends JPanel implements TableCellRenderer {

    private BasicStroke value;

    public TableCellLineRenderer(boolean isBordered) {
        setOpaque(true);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        if (value != null) {
            g2d.setStroke(value);
            g.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
        }

    }

    private void setLineType(BasicStroke value) {
        this.value = value;
    }

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        setBackground(Color.white);
        if (value instanceof BasicStroke) {
            setLineType((BasicStroke) value);
        } else {
            setLineType(null);
        }
        return this;
    }

}

ListCellLineRenderer:

import java.awt.Component;

@SuppressWarnings({ "rawtypes", "serial" })
public class ListCellLineRenderer extends JPanel implements ListCellRenderer {
    public ListCellLineRenderer() {
    }

    private LineStyle value;

    @Override
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        if (value instanceof LineStyle) {
            setLineType((LineStyle) value);
        } else {
            setLineType(null);
        }
        return this;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        if (value != null) {
            g2d.setStroke(value.getStroke());
            g.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
        }

    }

    private void setLineType(LineStyle value) {
        this.value = value;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(50, 20);
    }

}

枚举线条样式:

import java.awt.BasicStroke;
import java.awt.Stroke;

public enum LineStyle {

    one {
        @Override
        public Stroke getStroke() {
            return new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 4.0f);
        }
    },
    two {
        @Override
        public Stroke getStroke() {
            return new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 4.0f, pattern[1], 0.0f);
        }

    },
    three {
        @Override
        public Stroke getStroke() {
            return new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 4.0f, pattern[2], 0.0f);
        }

    },
    four {
        @Override
        public Stroke getStroke() {
            return new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER, 4.0f, pattern[3], 0.0f);
        }

    };

    private static float[][] pattern = { { 10.0f }, { 10.0f, 10.0f }, { 10.0f, 10.0f, 2.0f, 10.0f }, { 1.0f, 20.0f } };

    public abstract Stroke getStroke();
}

颜色生成器:

import java.awt.Color;
import java.util.Random;

public class ColorGenerator {

    public static Color generateColor() {

        Random rand = new Random();

        float r = rand.nextFloat();
        float g = rand.nextFloat();
        float b = rand.nextFloat();

        Color randomColor = new Color(r, g, b);

        return randomColor;
    }

}

【问题讨论】:

  • 未测试,请快速提问 JComboBox 中的项目已更改,如果单元格中的选择包含 JComboBox 也已更改,如果是,则调试模型中存储的内容
  • 模型中存储值一到四
  • 这只有在模型中的值存储最后选择的项目而不是数组的情况下才有可能,JComboBox 的所有值都存储在 DefaultComboBoxModel 中。 JTable 支持 JComboBox 作为 TableCellEditor,然后在 Model 中添加数组,将 Items 添加到 JComboBox,见TableComboBoxByRow 和用于渲染见Combo Box With Hidden Data,均由@camickr 制作
  • 并没有真正阅读您的问题,只是浏览了常见嫌疑人的代码:在 TableCellLineEditor 中找到了一个无效实现(终止编辑时不通知侦听器)
  • 不是在开玩笑,search for JComboBox as TableCellEditor,那么您就可以将选定的项目存储/获取/设置到 XxxTableModel(fireEditingXxx() 和 stopCellEditing()),但是您的数组表示的枚举可能是在 DefaultComboBoxRenderer 中呈现为线条/笔触,渲染器显示绘画,但 ItemListener 存储枚举,然后我链接到带有隐藏数据的组合框,ID 分布在各处,在您的情况下渲染器绘画线条

标签: java swing jtable jcombobox tablecelleditor


【解决方案1】:

好的,我终于解决了我的问题。这类似于替换每个单元格的“唯一”组合框。在 TableCellLineEditor 类中进行此修改后,它可以正常工作:

import java.awt.BasicStroke;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.AbstractCellEditor;
import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;

public class TableCellLineEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {

    JComboBox combobox;
    private BasicStroke val;
    protected static final String EDIT = "edit";

    public TableCellLineEditor() {

        combobox = new JComboBox(LineStyle.values());
        combobox.setRenderer(new ListCellLineRenderer());
        combobox.setActionCommand(EDIT);
        combobox.addActionListener(this);
    }

    @Override
    public Object getCellEditorValue() {
        return (BasicStroke) ((LineStyle) combobox.getSelectedItem()).getStroke();
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        val = (BasicStroke) value;

        for (int i = 0; i < LineStyle.values().length; i++) {
            if (val.equals(((BasicStroke) (LineStyle.values()[i]).getStroke()))) {
                combobox.setSelectedItem(LineStyle.values()[i]);
            }
        }
        return combobox;
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        if (EDIT.equals(e.getActionCommand())) {
            val = (BasicStroke) ((LineStyle) combobox.getSelectedItem()).getStroke();
            fireEditingStopped();
        } else {
            val = (BasicStroke) combobox.getSelectedItem();
        }
    }

}

谢谢大家的建议和回答:)

【讨论】:

    猜你喜欢
    • 2011-10-02
    • 2011-03-16
    • 2013-02-24
    • 2011-12-08
    • 2013-02-10
    • 2018-03-05
    • 2014-06-26
    • 2015-03-07
    • 1970-01-01
    相关资源
    最近更新 更多