【问题标题】:Render TableCell with JComboBox and selection background使用 JComboBox 和选择背景渲染 TableCell
【发布时间】:2011-08-08 08:42:28
【问题描述】:

如果有问题的列使用组合作为编辑器,我需要使用 JComboBoxJTable 中呈现选定/聚焦的单元格。这样做的目的是向用户提示该列中的单元格是使用组合而不是 JTextField 进行编辑的。

我的问题是,对于金属以外的其他LookAndFeels,不可能将表格的选择背景设置为组合框。如果单击或使用键盘导航到“组合列”,则所选单元格将由具有默认背景的组合呈现。

Metal L&F 可以按我的意愿工作,但这不是一个选项,因为我们的客户使用 Substance/Nimbus/Windows L&F,但对他们中的任何一个都不起作用。

希望我已经足够清楚了,感谢任何帮助!

选择此 SSCCE 的“组合列”中的单元格以了解我的意思:

import java.awt.Component;

import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

import com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel;


public class RenderSelectedCellWithComboSSCCE extends JFrame
{   
    RenderSelectedCellWithComboSSCCE()
    {
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        add(new JScrollPane(createTable()));
        pack();
    }

    private JTable createTable()
    {
        TableModel model = new DefaultTableModel(
                new Object [][] {{"A", "Item 0"},
                                 {"B", "Item 1"},
                                 {"C", "Item 2"},
                                 {"D", "Item 3"},
                                 {"E", "Item 4"}},
                new String [] {"TextField", "Combo"});
        JTable table = new JTable(model);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        DefaultCellEditor editor = new DefaultCellEditor(new JComboBox(new Object[]{"Item 0", "Item 1", "Item 2", "Item 3", "Item 4"}));
        editor.setClickCountToStart(2);
        table.getColumnModel().getColumn(1).setCellEditor(editor);
        table.getColumnModel().getColumn(1).setCellRenderer(new ComboCellRenderer());
        return table;
    }

    /**
     * Renderer that demonstrates problem rendering selected cells with a combo with selection background.
     */
    private static class ComboCellRenderer implements TableCellRenderer
    {
        final TableCellRenderer defaultRenderer;
        final JComboBox combo;

        ComboCellRenderer()
        {
            defaultRenderer = new DefaultTableCellRenderer();
            combo = new JComboBox();
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
        {
            if (hasFocus && table != null && table.isCellEditable(row, column))
            {
                combo.setModel(new DefaultComboBoxModel(new Object[]{value}));
                combo.setSelectedItem(value);
                combo.setBackground(table.getSelectionBackground());    // This only have desired effect for Metal L&F
                return combo;
            }
            else
            {
                return defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            }
        }
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                setLookAndFeel();
                new RenderSelectedCellWithComboSSCCE().setVisible(true);
            }

            private void setLookAndFeel()
            {
                try
                {
                    //UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());       // Metal works fine
                    UIManager.setLookAndFeel(new NimbusLookAndFeel());
                    //UIManager.setLookAndFeel(new WindowsLookAndFeel());
                    //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    //UIManager.setLookAndFeel("org.jvnet.substance.SubstanceLookAndFeel");
                }
                catch (Exception e)
                {
                    throw new RuntimeException("Failed to set LookAndFeel", e);
                }
            }
        });
    }
}

【问题讨论】:

    标签: java swing jtable renderer nimbus


    【解决方案1】:

    ComboBox 渲染确实会带来问题,通常 LAF 对如何显示组合本身有非常特殊的想法,许多都是样式化的,有圆角……它不可能对所有人都正确。在玩了一下 Stani 的建议时,我遇到了所有令人讨厌的(很快就忘记了:-) 细节,比如

    • Windows 在渲染组合时关闭不透明度,因此在这里将组合的渲染器包装成一个在调用 super 后将不透明度设置为 true 的渲染器会有所帮助
    • Nimbus 会忽略自己设置的组件背景,无论不透明度如何:如果您设置不同的选择颜色(在桌子上),您的渲染器将按预期工作(好吧,几乎,模数意外的颜色变化 :-)从默认
    • ...

    另一方面,您不需要功能齐全的 JComboBox,您所需要的只是一个视觉线索,表明有东西可以打开。因此,您可能会使用自定义组件 - 最简单的是带有一些箭头的 JLabel - 模拟 JComboBox,例如:

    public static class MockCombo extends JLabel {
    
        private JButton arrow;
    
        public MockCombo() {
            JComboBox box = new JComboBox();
            box.setEditable(true);
            arrow = (JButton) box.getComponent(0);
            setLayout(new BorderLayout());
            add(arrow, BorderLayout.LINE_END);
            setOpaque(true);
        }
    
    }
    

    仍然需要通过 LAF 进行微调,但比调整 JComboBox 容易得多

    【讨论】:

    • hmmmm,只是问题->为什么 setOpaque(true);对于为 TableCellRenderer 提取的 JComponents,也许我错了,但是如果 TableCell 包含另一个 JComponet 作为 JLabel,那么我将 Nimbus L&F 放在任何地方 setOpaque(false); +1
    【解决方案2】:

    您可以指定组合渲染器并在那里使用所需的颜色。渲染组件的渲染器类型。

    【讨论】:

    • 我已经尝试过了,但是没有用。你有什么代码要提供吗?
    • 删除了我之前的评论 - 忘记实际安装组合的渲染器 ;-) 所以,是的,如果不是针对每个 LAF 进行专门化,它是可能的,但可能很难看..
    猜你喜欢
    • 2017-09-24
    • 2022-10-24
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 2014-11-20
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多