尝试在 JTable 中替换布尔复选框渲染器/编辑器 [英] Trying to Replace Boolean CheckBox renderer/editor in JTable

查看:36
本文介绍了尝试在 JTable 中替换布尔复选框渲染器/编辑器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个允许对项目进行收藏的 JTable,但不幸的是,正确的图像不会在初始渲染时显示出来,然后不会正确更新,直到它们在单元格中失去焦点.

为此,我将第 1 列设为字符串,将第 2 列设为布尔值.然后我根据这个问题覆盖了布尔渲染器/编辑器:

我现在单击右下角使该单元格失去焦点,然后用正确的图像填充自己.

最后我点击你看到复选标记的地方

附加说明:我自己添加了 revalidate() 和 repaint(),没有它,行为基本相同,只是在初始渲染后不再显示复选标记.在失去焦点之前它仍然不会更新图像

解决方案

如果您只有一列布尔值,那么您可以自定义复选框编辑器和渲染器使用的图标:

import java.awt.*;导入 java.awt.event.*;导入 java.util.*;导入 javax.swing.*;导入 javax.swing.table.*;导入 javax.swing.border.*;导入 java.text.*;公共类 TableBasic 扩展了 JPanel{公共表基本(){setLayout(new BorderLayout());String[] columnNames = {"Date", "String", "Integer", "Boolean"};对象[][] 数据 ={{new Date(), "A", new Integer(1), Boolean.TRUE },{new Date(), "B", new Integer(2), Boolean.FALSE},{new Date(), "C", new Integer(12), Boolean.TRUE },{new Date(), "D", new Integer(5124), Boolean.FALSE}};DefaultTableModel 模型 = 新的 DefaultTableModel(data, columnNames){//返回每一列的类将允许不同的//基于类使用的渲染器和编辑器@覆盖公共类 getColumnClass(int column){for (int row = 0; row < getRowCount(); row++){Object o = getValueAt(row, column);如果 (o != null)返回 o.getClass();}返回 Object.class;}};JTable table = new JTable(model);table.setPreferredScrollableViewportSize(table.getPreferredSize());JScrollPane scrollPane = new JScrollPane( table );添加(滚动窗格);//自定义用于布尔数据的渲染器/编辑器的图标Icon selectedIcon = new ImageIcon("copy16.gif");Icon icon = new ImageIcon("about16.gif");DefaultCellEditor dce = (DefaultCellEditor)table.getDefaultEditor(Boolean.class);JCheckBox cbe = (JCheckBox)dce.getComponent();cbe.setSelectedIcon( selectedIcon );cbe.setIcon(图标);TableCellRenderer tcr = table.getDefaultRenderer(Boolean.class);JCheckBox cbr = (JCheckBox)tcr;cbr.setSelectedIcon( selectedIcon );cbr.setIcon(图标);}私有静态无效 createAndShowUI(){JFrame frame = new JFrame("TableBasic");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.add( new TableBasic() );框架.pack();frame.setLocationRelativeTo( null );frame.setVisible(true);}public static void main(String[] args){EventQueue.invokeLater(new Runnable(){公共无效运行(){createAndShowUI();}});}}

如果您需要多个布尔渲染器/编辑器,那么您需要为每个渲染器/编辑器创建唯一的实例.

创建编辑器很容易.您只需使用自定义 JCheckBox 创建一个 DefaultCellEditor:

JCheckBox checkBox = new JCheckBox();checkBox.setHorizo​​ntalAlignment(JCheckBox.CENTER);checkBox.setSelectedIcon( selectedIcon );checkBox.setIcon(图标);DefaultCellEditor dce = new DefaultCellEditor( checkBox );table.getColumnModel().getColumn(???).setCellEditor(dce);

创建渲染器更加困难.您需要创建一个自定义渲染器.以下是 JTable 源代码中 BooleanRenderer 的默认渲染器代码:

static class BooleanRenderer extends JCheckBox 实现 TableCellRenderer, UIResource{private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);公共布尔渲染器(){极好的();setHorizo​​ntalAlignment(JLabel.CENTER);setBorderPainted(true);}公共组件 getTableCellRendererComponent(JTable 表,对象值,boolean isSelected, boolean hasFocus, int row, int column) {如果(被选中){setForeground(table.getSelectionForeground());super.setBackground(table.getSelectionBackground());}别的 {setForeground(table.getForeground());setBackground(table.getBackground());}setSelected((value != null && ((Boolean)value).booleanValue()));如果(有焦点){setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));} 别的 {setBorder(noFocusBorder);}返回这个;}}

在构造函数中,您将设置图标.

I am trying to create a JTable that allows for favoriting of items, but unfortunately the correct images do not show up on initial rendering, and then do not update properly until they lose focus in the cell.

To do this I've made column 1 a String and column 2 a boolean. I then overwrote the boolean renderer/editor as based on this question:

Java Swing, Trying to replace boolean check-box in a JTable with an image-icon checkbox

what I currently have:

public class FavoritableCellEditor extends AbstractCellEditor implements TableCellEditor {

private final FavoriteCheckBox cellEditor;

public FavoritableCellEditor() {
    cellEditor = new FavoriteCheckBox();
}

@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
    if (value instanceof Boolean) {
        boolean selected = (boolean) value;
        cellEditor.setSelected(selected);
    }
    return cellEditor;
}

@Override
public Object getCellEditorValue() {
    return cellEditor.isSelected();
}

}


public class FavoritableCheckboxRenderer extends FavoriteCheckBox implements TableCellRenderer {


@Override
public void setSelected(boolean selected) {
    super.setSelected(selected);
    if (selected) {
        setIcon(selIcon);
    } else {
        setIcon(unselIcon);
    }
}

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    if (value instanceof Boolean) {
        boolean selected = (boolean) value;
        setSelected(selected);
    }
    return this;
}
}

public class FavoriteCheckBox extends JCheckBox {

    Icon selIcon;
    Icon unselIcon;

    public FavoriteCheckBox() {
        try {
            selIcon = new ImageIcon(ImageIO.read(getClass().getResource("/com/lmco/jsf/dqim/applications/TESTING/resources/baseline_star_black_18dp.png")));
            unselIcon = new ImageIcon(ImageIO.read(getClass().getResource("/com/lmco/jsf/dqim/applications/TESTING/resources/baseline_star_border_black_18dp.png")));
        } catch (IOException ex) {
            Logger.getLogger(FavoriteCheckBox.class.getName()).log(Level.SEVERE, null, ex);
        }
        setHorizontalAlignment(CENTER);
    }

    @Override
    public void setSelected(boolean selected) {
        super.setSelected(selected);
        if (selected) {
            setIcon(selIcon);
        } else {
            setIcon(unselIcon);
        }
        revalidate();
        repaint();
    }

}

Demonstration: I initially click where you see the check mark. Currently the correct images are not showing, but the default checkbox images.

I now click the bottom right corner to make that cell lose focus, it then paints itself filled with the correct image.

Finally I click where you see the check mark

An additional note: I've added in the revalidate() and repaint() myself, without it the behavior is largely the same except that it will never show the check marks again after initial rendering. It will still not update the image until focus is lost

解决方案

If you only have a single column of Boolean values then you can just customize the icons used by the check box editor and renderer:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.border.*;
import java.text.*;

public class TableBasic extends JPanel
{
    public TableBasic()
    {
        setLayout( new BorderLayout() );

        String[] columnNames = {"Date", "String", "Integer", "Boolean"};

        Object[][] data =
        {
            {new Date(), "A", new Integer(1), Boolean.TRUE },
            {new Date(), "B", new Integer(2), Boolean.FALSE},
            {new Date(), "C", new Integer(12), Boolean.TRUE },
            {new Date(), "D", new Integer(5124), Boolean.FALSE}
        };

        DefaultTableModel model = new DefaultTableModel(data, columnNames)
        {
            //  Returning the Class of each column will allow different
            //  renderers and editors to be used based on Class

            @Override
            public Class getColumnClass(int column)
            {
                for (int row = 0; row < getRowCount(); row++)
                {
                    Object o = getValueAt(row, column);

                    if (o != null)
                        return o.getClass();
                }

                return Object.class;
            }
        };

        JTable table = new JTable(model);

        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane( table );
        add( scrollPane );

        // Customize the icons of the renderer/editor used for Boolean data

        Icon selectedIcon = new ImageIcon( "copy16.gif" );
        Icon icon = new ImageIcon( "about16.gif" );

        DefaultCellEditor dce = (DefaultCellEditor)table.getDefaultEditor(Boolean.class);
        JCheckBox cbe = (JCheckBox)dce.getComponent();
        cbe.setSelectedIcon( selectedIcon );
        cbe.setIcon( icon );

        TableCellRenderer tcr = table.getDefaultRenderer(Boolean.class);
        JCheckBox cbr = (JCheckBox)tcr;
        cbr.setSelectedIcon( selectedIcon );
        cbr.setIcon( icon );
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("TableBasic");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new TableBasic() );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

If you need multiple Boolean renderers/editors then you will need to create unique instances of each renderer/editor.

Creating the editor is easy. You just create a DefaultCellEditor using your custom JCheckBox:

JCheckBox checkBox = new JCheckBox();
checkBox.setHorizontalAlignment(JCheckBox.CENTER);
checkBox.setSelectedIcon( selectedIcon );
checkBox.setIcon( icon );
DefaultCellEditor dce = new DefaultCellEditor( checkBox );
table.getColumnModel().getColumn(???).setCellEditor(dce);

Creating the renderer is more difficult. You need to create an custom renderer. Here is the default renderer code for the BooleanRenderer as found in the JTable source:

static class BooleanRenderer extends JCheckBox implements TableCellRenderer, UIResource
{
    private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);

    public BooleanRenderer() {
        super();
        setHorizontalAlignment(JLabel.CENTER);
        setBorderPainted(true);
    }

    public Component getTableCellRendererComponent(JTable table, Object value,
                                                   boolean isSelected, boolean hasFocus, int row, int column) {
        if (isSelected) {
            setForeground(table.getSelectionForeground());
            super.setBackground(table.getSelectionBackground());
        }
        else {
            setForeground(table.getForeground());
            setBackground(table.getBackground());
        }
        setSelected((value != null && ((Boolean)value).booleanValue()));

        if (hasFocus) {
            setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
        } else {
            setBorder(noFocusBorder);
        }

        return this;
    }
}

In the constructor you would set the icons.

这篇关于尝试在 JTable 中替换布尔复选框渲染器/编辑器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆