Question

The problem is, when user clicks on a cell with style of line, and chooses one of 4 options and after that clicks on other cell with line style, after that, that other cell displays line style, choosen in previous selected cell. How to, make that line style unique for every cell (different line styles in different cells) in "line style" column? Cells in "line colour" column works fine and they are implemented similarly.

Here is the SSCCE:

Main Class:

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

Panel:

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

}

enum LineStyle:

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

ColorGenerator:

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

}
Was it helpful?

Solution

Ok, finally I've solved my problem. This is something like replacement for "unique" combobox for every cell. It works, works fine, after this modification in TableCellLineEditor class:

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

}

Thank You all, for your suggestions, and answers :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top