【问题标题】:JTable Nimbus Look and Feel - how to make it clear which cell has focusJTable Nimbus 外观和感觉 - 如何明确哪个单元格具有焦点
【发布时间】:2012-07-01 04:32:34
【问题描述】:

在 JTable (Nimbus L & F) 中编辑数据时,当用户从一个单元格切换到另一个单元格时,哪个单元格具有焦点并不明显。我怎样才能更清楚哪个单元格有焦点?我知道可以设置许多属性来修改 Nimbus - 有人知道我想要哪个属性吗?

下面的屏幕截图只有一个属性设置为非默认值:

UIManager.put("Table.showGrid", true);

【问题讨论】:

    标签: java swing jtable nimbus tablecelleditor


    【解决方案1】:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Pattern;
    import javax.swing.Icon;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.RowSorter.SortKey;
    import javax.swing.SortOrder;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.TableColumn;
    import javax.swing.table.TableModel;
    import javax.swing.table.TableRowSorter;
    
    public class ImageChangeDemo extends JFrame {
    
        private static final long serialVersionUID = 1L;
        private JTable table = new javax.swing.JTable();
        private JTable table1 = new javax.swing.JTable();
        private static Icon ascendingSortIcon;
        private static Icon descendingSortIcon;
    
        public static void main(String args[]) {
            //comment out the code below to try in Metal L&F
            try {
                for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(info.getName())) {
                        javax.swing.UIManager.setLookAndFeel(info.getClassName());
                        ascendingSortIcon = UIManager.getLookAndFeelDefaults().getIcon("Table.ascendingSortIcon");
                        descendingSortIcon = UIManager.getLookAndFeelDefaults().getIcon("Table.descendingSortIcon");
                        //UIManager.getLookAndFeelDefaults().put("Table.ascendingSortIcon", new BevelArrowIcon(BevelArrowIcon.UP, false, false));
                        //UIManager.getLookAndFeelDefaults().put("Table.descendingSortIcon", new BevelArrowIcon(BevelArrowIcon.DOWN, false, false));
                        break;
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            java.awt.EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    new ImageChangeDemo().setVisible(true);
                }
            });
        }
    
        public ImageChangeDemo() {
            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
            JScrollPane pane = new javax.swing.JScrollPane();
            //table.setAutoCreateRowSorter(true);
            table.setModel(new javax.swing.table.DefaultTableModel(
                    new Object[][]{
                        {"a", "q", "h", "v"},
                        {"b", "m", "l", "h"},
                        {"d", "c", "a", "d"},
                        {"j", "o", "y", "e"}
                    },
                    new String[]{
                        "Col 1", "Col 2", "Col 3", "Col 4"
                    }) {
    
                private static final long serialVersionUID = 1L;
                Class[] types = new Class[]{
                    String.class, String.class, String.class, String.class
                };
    
                @Override
                public Class getColumnClass(int columnIndex) {
                    return types[columnIndex];
                }
            });
            TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()) {
    
                @Override
                public void toggleSortOrder(int column) {
                    if (column >= 0 && column < getModelWrapper().getColumnCount() && isSortable(column)) {
                        List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
                        if (!keys.isEmpty()) {
    
                            SortKey sortKey = keys.get(0);
                            if (sortKey.getColumn() == column && sortKey.getSortOrder() == SortOrder.DESCENDING) {
                                setSortKeys(null);
                                return;
                            }
                        }
                    }
                    super.toggleSortOrder(column);
                }
            };
            table.setRowSorter(sorter);
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            pane.setViewportView(table);
            UIManager.getLookAndFeelDefaults().put("Table.ascendingSortIcon", new BevelArrowIcon(BevelArrowIcon.UP, false, false));
            UIManager.getLookAndFeelDefaults().put("Table.descendingSortIcon", new BevelArrowIcon(BevelArrowIcon.DOWN, false, false));
            SwingUtilities.updateComponentTreeUI(table);
            add(pane, BorderLayout.NORTH);
            JScrollPane pane1 = new javax.swing.JScrollPane();
            //table.setAutoCreateRowSorter(true);
            table1.setModel(new javax.swing.table.DefaultTableModel(
                    new Object[][]{
                        {"a", "q", "h", "v"},
                        {"b", "m", "l", "h"},
                        {"d", "c", "a", "d"},
                        {"j", "o", "y", "e"}
                    },
                    new String[]{
                        "Col 1", "Col 2", "Col 3", "Col 4"
                    }) {
    
                private static final long serialVersionUID = 1L;
                Class[] types = new Class[]{
                    String.class, String.class, String.class, String.class
                };
    
                @Override
                public Class getColumnClass(int columnIndex) {
                    return types[columnIndex];
                }
            });
            table1.setRowSorter(sorter);
            table1.setPreferredScrollableViewportSize(table1.getPreferredSize());
            pane1.setViewportView(table1);
            add(pane1, BorderLayout.SOUTH);
    
            for (int i = 0; i < table1.getColumnCount(); i++) {
                RowColorRenderer rowRenderer = new RowColorRenderer(i);
                TableColumn column = table1.getColumnModel().getColumn(i);
                column.setCellRenderer(rowRenderer);
            }
            pack();
        }
    
        private class RowColorRenderer extends DefaultTableCellRenderer {
    
            private static final long serialVersionUID = 1L;
            private int colNo = 0;
    
            RowColorRenderer(int col) {
                colNo = col;
            }
    
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value,
                    boolean isSelected, boolean hasFocus, int row, int column) {
                Component comp = super.getTableCellRendererComponent(table, value,
                        isSelected, hasFocus, row, column);
                JComponent jc = (JComponent) comp;
                if (!isSelected) {
                    if (table.getValueAt(row, colNo) != null) {
                        String str = table.getValueAt(row, colNo).toString();
                        if (!str.isEmpty()) {
                            if (Pattern.compile("\\d").matcher(str).find()) {
                                if (((Pattern.compile("[02468]").matcher(str).find()))
                                        && (!(Pattern.compile("[13579]").matcher(str).find()))) {
                                    setForeground(Color.magenta);
                                    setBackground(Color.orange);
                                } else if ((!(Pattern.compile("[02468]").matcher(str).find()))
                                        && ((Pattern.compile("[13579]").matcher(str).find()))) {
                                    setForeground(Color.blue);
                                    setBackground(Color.yellow);
                                } else if (((Pattern.compile("[02468]").matcher(str).find()))
                                        && ((Pattern.compile("[13579]").matcher(str).find()))) {
                                    setForeground(Color.red);
                                    setBackground(Color.cyan);
                                }
                                setFont(new Font("Serif", Font.BOLD, 12));
                                setHorizontalAlignment(CENTER);
                            } else {
                                setBackground(table.getBackground());
                                setForeground(table.getForeground());
                                setFont(new Font("Serif", Font.PLAIN, 8));
                                setHorizontalAlignment(CENTER);
                            }
                        }
                    }
                } else {
                    if (hasFocus) {
                        setFont(new Font("Serif", Font.BOLD, 12));
                        setForeground(Color.magenta);
                        setBackground(Color.orange);
                    }
                }
                return this;
            }
        }
    
        static class BevelArrowIcon implements Icon {
    
            public static final int UP = 0;         // direction
            public static final int DOWN = 1;
            private static final int DEFAULT_SIZE = 11;
            private Color edge1;
            private Color edge2;
            private Color fill;
            private int size;
            private int direction;
    
            public BevelArrowIcon(int direction, boolean isRaisedView, boolean isPressedView) {
                if (isRaisedView) {
                    if (isPressedView) {
                        init(UIManager.getColor("controlLtHighlight"), UIManager.getColor("controlDkShadow"), UIManager.getColor("controlShadow"), DEFAULT_SIZE, direction);
                    } else {
                        init(UIManager.getColor("controlHighlight"), UIManager.getColor("controlShadow"), UIManager.getColor("control"), DEFAULT_SIZE, direction);
                    }
                } else {
                    if (isPressedView) {
                        init(UIManager.getColor("controlDkShadow"), UIManager.getColor("controlLtHighlight"), UIManager.getColor("controlShadow"), DEFAULT_SIZE, direction);
                    } else {
                        init(UIManager.getColor("controlShadow"), UIManager.getColor("controlHighlight"), UIManager.getColor("control"), DEFAULT_SIZE, direction);
                    }
                }
            }
    
            public BevelArrowIcon(Color edge1, Color edge2, Color fill, int size, int direction) {
                init(edge1, edge2, fill, size, direction);
            }
    
            @Override
            public void paintIcon(Component c, Graphics g, int x, int y) {
                switch (direction) {
                    case DOWN:
                        drawDownArrow(g, x, y);
                        break;
                    case UP:
                        drawUpArrow(g, x, y);
                        break;
                }
            }
    
            @Override
            public int getIconWidth() {
                return size;
            }
    
            @Override
            public int getIconHeight() {
                return size;
            }
    
            private void init(Color edge1, Color edge2, Color fill, int size, int direction) {
                edge1 = Color.red;
                edge2 = Color.blue;
                this.edge1 = edge1;
                this.edge2 = edge2;
                this.fill = fill;
                this.size = size;
                this.direction = direction;
            }
    
            private void drawDownArrow(Graphics g, int xo, int yo) {
                g.setColor(edge1);
                g.drawLine(xo, yo, xo + size - 1, yo);
                g.drawLine(xo, yo + 1, xo + size - 3, yo + 1);
                g.setColor(edge2);
                g.drawLine(xo + size - 2, yo + 1, xo + size - 1, yo + 1);
                int x = xo + 1;
                int y = yo + 2;
                int dx = size - 6;
                while (y + 1 < yo + size) {
                    g.setColor(edge1);
                    g.drawLine(x, y, x + 1, y);
                    g.drawLine(x, y + 1, x + 1, y + 1);
                    if (0 < dx) {
                        g.setColor(fill);
                        g.drawLine(x + 2, y, x + 1 + dx, y);
                        g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
                    }
                    g.setColor(edge2);
                    g.drawLine(x + dx + 2, y, x + dx + 3, y);
                    g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
                    x += 1;
                    y += 2;
                    dx -= 2;
                }
                g.setColor(edge1);
                g.drawLine(xo + (size / 2), yo + size - 1, xo + (size / 2), yo + size - 1);
            }
    
            private void drawUpArrow(Graphics g, int xo, int yo) {
                g.setColor(edge1);
                int x = xo + (size / 2);
                g.drawLine(x, yo, x, yo);
                x--;
                int y = yo + 1;
                int dx = 0;
                while (y + 3 < yo + size) {
                    g.setColor(edge1);
                    g.drawLine(x, y, x + 1, y);
                    g.drawLine(x, y + 1, x + 1, y + 1);
                    if (0 < dx) {
                        g.setColor(fill);
                        g.drawLine(x + 2, y, x + 1 + dx, y);
                        g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
                    }
                    g.setColor(edge2);
                    g.drawLine(x + dx + 2, y, x + dx + 3, y);
                    g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
                    x -= 1;
                    y += 2;
                    dx += 2;
                }
                g.setColor(edge1);
                g.drawLine(xo, yo + size - 3, xo + 1, yo + size - 3);
                g.setColor(edge2);
                g.drawLine(xo + 2, yo + size - 2, xo + size - 1, yo + size - 2);
                g.drawLine(xo, yo + size - 1, xo + size, yo + size - 1);
            }
        }
    }
    

    【讨论】:

    • 谢谢!这正是我一直在寻找的,然后是一些。您甚至只是为了好玩而使用自定义排序图标:)(Nimbus Default 很好,但无论如何谢谢。)很好的例子来说明什么是可能的。
    • 很高兴为您提供帮助,请注意我仍然不确定,如果您需要为 TableCellEditor 做同样的事情 :-)
    • 如果我希望在编辑时保持焦点颜色,我需要对 TableCellEditor 执行相同的操作。至此,我完全明白了如何做到这一点,剩下的就是决定做什么。 TableCellEditor 解释了为什么在用户开始编辑焦点单元格后,外观会发生变化(从选定的行颜色变为白色背景)。这可能就是我想要的——我不确定这是否重要。这个问题并不是关于外观,而是关于让表格更直观和更实用,因为我的一些用户,比如说不精通。
    • 有些事情对我来说简直是..无法实现的,以我的(伟大的,优秀的,无与伦比的,e.i.其余最高级的)书面和口头英语,
    【解决方案2】:

    您需要创建一个自定义单元格渲染器类,例如,如果选择该类,它将更改前景色。

    您的类将扩展 DefaultTableCellRenderer覆盖方法 getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)

    例如

    public class SpreadsheetCellRenderer extends DefaultTableCellRenderer {
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            /* the following is the similar to DefaultTableCellRenderer */
            if (isSelected) {
                super.setForeground(Color.red);
            } else {
                super.setForeground(Color.black);
            }
        setText(value.toString());
        return this;
        }
    }
    

    然后您需要将该渲染器设置为默认渲染器,以便通过执行此操作来表示表中的字符串对象。

    table.setDefaultRenderer(Class.forName("java.lang.String"), new SpreadsheetCellRenderer());
    

    【讨论】:

    • 顺便说一下,我显然展示了 Nimbus 之外的机制,但这是更改 JTable 属性的一般方法。
    • 我知道 TableCellRenderer 并且正在寻找一种更简单的方法,但感谢您提供清晰的示例。创建自定义单元格渲染器比我想象的要容易。但我希望从这里得到一些东西:jasperpotts.com/blogfiles/nimbusdefaults/nimbus.html
    • @Thorn 我会在这里取消删除我的答案,没问题
    • 我在外观和感觉方面做得不多,我一直在开发自己的组件并使用渲染器来改变外观。但是你不能这样做吗? UIManager.getLookAndFeelDefaults().put("Table[Selected].textForeground", "#ff0000");
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-14
    • 2013-03-21
    • 2013-04-09
    • 2015-04-24
    • 2011-02-27
    • 1970-01-01
    相关资源
    最近更新 更多