如何为JTable复选框标题添加边框

时间:2013-11-19 15:12:55

标签: java swing user-interface jtable

我发现this code要在JTable上创建标题组件,但我无法为默认标头提供相同的边框。以下是代码的屏幕截图:

screenshot

此处全选复选框与第1列和第2列的边框不同,因此它看起来不同。而且与列中的向上相比,它的水平有点低。

源代码如下: -

package com.test.check.table;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;

public class SelectAllHeaderTest {

    private static final int BOOLEAN_COL = 2;
    private static final Object colNames[] = {"Column 1", "Column 2", ""};
    private DefaultTableModel model = new DefaultTableModel(null, colNames) {

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            if (columnIndex == BOOLEAN_COL) {
                return Boolean.class;
            } else {
                return String.class;
            }
        }
    };
    private JTable table = new JTable(model);

    public void create() {
        for (int x = 1; x < 6; x++) {
            model.addRow(new Object[]{
                    "Row " + x + ", Col 1", "Row " + x + ", Col 2", false
                });
        }
        table.setAutoCreateRowSorter(true);
        table.setPreferredScrollableViewportSize(new Dimension(320, 160));
        TableColumn tc = table.getColumnModel().getColumn(BOOLEAN_COL);
        tc.setHeaderRenderer(new SelectAllHeader(table, BOOLEAN_COL));
        String newLookAndFeel = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
        try {
            UIManager.setLookAndFeel(newLookAndFeel);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        JFrame f = new JFrame();
        f.add(new JScrollPane(table));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new SelectAllHeaderTest().create();
            }
        });
    }
}

/**
 * A TableCellRenderer that selects all or none of a Boolean column.
 * 
 * @param targetColumn the Boolean column to manage
 */
class SelectAllHeader extends JCheckBox implements TableCellRenderer {

    private static final String ALL = "Select all";
    private static final String NONE = "Select none";
    private JTable table;
    private TableModel tableModel;
    private JTableHeader header;
    private TableColumnModel tcm;
    private int targetColumn;
    private int viewColumn;

    public SelectAllHeader(JTable table, int targetColumn) {
        super(ALL);
        this.table = table;
        this.tableModel = table.getModel();
        if (tableModel.getColumnClass(targetColumn) != Boolean.class) {
            throw new IllegalArgumentException("Boolean column required.");
        }
        this.targetColumn = targetColumn;
        this.header = table.getTableHeader();
        this.tcm = table.getColumnModel();
        this.applyUI();
        this.addItemListener(new ItemHandler());
        header.addMouseListener(new MouseHandler());
        tableModel.addTableModelListener(new ModelHandler());
    }

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

    private class ItemHandler implements ItemListener {

        @Override
        public void itemStateChanged(ItemEvent e) {
            boolean state = e.getStateChange() == ItemEvent.SELECTED;
            setText((state) ? NONE : ALL);
            for (int r = 0; r < table.getRowCount(); r++) {
                table.setValueAt(state, r, viewColumn);
            }
        }
    }

    @Override
    public void updateUI() {
        super.updateUI();
        applyUI();
    }

    private void applyUI() {
        this.setFont(UIManager.getFont("TableHeader.font"));
        this.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
        this.setBackground(UIManager.getColor("TableHeader.background"));
        this.setForeground(UIManager.getColor("TableHeader.foreground"));
    }

    private class MouseHandler extends MouseAdapter {

        @Override
        public void mouseClicked(MouseEvent e) {
            viewColumn = header.columnAtPoint(e.getPoint());
            int modelColumn = tcm.getColumn(viewColumn).getModelIndex();
            if (modelColumn == targetColumn) {
                doClick();
            }
        }
    }

    private class ModelHandler implements TableModelListener {

        @Override
        public void tableChanged(TableModelEvent e) {
            if (needsToggle()) {
                doClick();
                header.repaint();
            }
        }
    }

    // Return true if this toggle needs to match the model.
    private boolean needsToggle() {
        boolean allTrue = true;
        boolean allFalse = true;
        for (int r = 0; r < tableModel.getRowCount(); r++) {
            boolean b = (Boolean) tableModel.getValueAt(r, targetColumn);
            allTrue &= b;
            allFalse &= !b;
        }
        return allTrue && !isSelected() || allFalse && isSelected();
    }
}

package com.test.check.table; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.*; public class SelectAllHeaderTest { private static final int BOOLEAN_COL = 2; private static final Object colNames[] = {"Column 1", "Column 2", ""}; private DefaultTableModel model = new DefaultTableModel(null, colNames) { @Override public Class<?> getColumnClass(int columnIndex) { if (columnIndex == BOOLEAN_COL) { return Boolean.class; } else { return String.class; } } }; private JTable table = new JTable(model); public void create() { for (int x = 1; x < 6; x++) { model.addRow(new Object[]{ "Row " + x + ", Col 1", "Row " + x + ", Col 2", false }); } table.setAutoCreateRowSorter(true); table.setPreferredScrollableViewportSize(new Dimension(320, 160)); TableColumn tc = table.getColumnModel().getColumn(BOOLEAN_COL); tc.setHeaderRenderer(new SelectAllHeader(table, BOOLEAN_COL)); String newLookAndFeel = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; try { UIManager.setLookAndFeel(newLookAndFeel); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedLookAndFeelException e) { // TODO Auto-generated catch block e.printStackTrace(); } JFrame f = new JFrame(); f.add(new JScrollPane(table)); f.pack(); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new SelectAllHeaderTest().create(); } }); } } /** * A TableCellRenderer that selects all or none of a Boolean column. * * @param targetColumn the Boolean column to manage */ class SelectAllHeader extends JCheckBox implements TableCellRenderer { private static final String ALL = "Select all"; private static final String NONE = "Select none"; private JTable table; private TableModel tableModel; private JTableHeader header; private TableColumnModel tcm; private int targetColumn; private int viewColumn; public SelectAllHeader(JTable table, int targetColumn) { super(ALL); this.table = table; this.tableModel = table.getModel(); if (tableModel.getColumnClass(targetColumn) != Boolean.class) { throw new IllegalArgumentException("Boolean column required."); } this.targetColumn = targetColumn; this.header = table.getTableHeader(); this.tcm = table.getColumnModel(); this.applyUI(); this.addItemListener(new ItemHandler()); header.addMouseListener(new MouseHandler()); tableModel.addTableModelListener(new ModelHandler()); } @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { return this; } private class ItemHandler implements ItemListener { @Override public void itemStateChanged(ItemEvent e) { boolean state = e.getStateChange() == ItemEvent.SELECTED; setText((state) ? NONE : ALL); for (int r = 0; r < table.getRowCount(); r++) { table.setValueAt(state, r, viewColumn); } } } @Override public void updateUI() { super.updateUI(); applyUI(); } private void applyUI() { this.setFont(UIManager.getFont("TableHeader.font")); this.setBorder(UIManager.getBorder("TableHeader.cellBorder")); this.setBackground(UIManager.getColor("TableHeader.background")); this.setForeground(UIManager.getColor("TableHeader.foreground")); } private class MouseHandler extends MouseAdapter { @Override public void mouseClicked(MouseEvent e) { viewColumn = header.columnAtPoint(e.getPoint()); int modelColumn = tcm.getColumn(viewColumn).getModelIndex(); if (modelColumn == targetColumn) { doClick(); } } } private class ModelHandler implements TableModelListener { @Override public void tableChanged(TableModelEvent e) { if (needsToggle()) { doClick(); header.repaint(); } } } // Return true if this toggle needs to match the model. private boolean needsToggle() { boolean allTrue = true; boolean allFalse = true; for (int r = 0; r < tableModel.getRowCount(); r++) { boolean b = (Boolean) tableModel.getValueAt(r, targetColumn); allTrue &= b; allFalse &= !b; } return allTrue && !isSelected() || allFalse && isSelected(); } } 从上面的代码我试图给复选框标题边框,但它看起来不像预期(上部和宝石边框)。

任何有关制作鞋面的建议都将受到高度赞赏。

由于

2 个答案:

答案 0 :(得分:1)

你改变了,在运行时设置了L&amp; F,创建了Swing对象的一部分但是没有使用新的L&amp; F(Metal to Windows)刷新RootPane

开始
  • 在代码行public static void main(String[] args) {

  • 之前将L&amp; F放到主要课程的SwingUtilities.invokeLater(new Runnable() {
  • 然后您(代码在谈论)与JToggleButton中的JTableHeader保持一致

    a)leave that, will be better and nicer

    b)删除JToggleButton的背景信息或设置opacity,更改Borders为未修饰的JToggleButton(模仿JTableHeader中的单元格)

    < / LI>
  • original code posted and screenshot by @trashgod is from Mac OSX and there is used own L&F

答案 1 :(得分:0)

根据建议,我设置了标题的边框,如

在复选框渲染器中。我修改它如下: -

header.setBorder(BorderFactory.createRaisedBevelBorder());

在runnable之前,还将我的L&amp; F代码放在静态main方法中。

它以正确的方式显示边框,我的复选框看起来很好。

非常感谢您的代码!最后它工作正常。