【问题标题】:LookAndFeel blocking JComboBox background change?LookAndFeel 阻止 JComboBox 背景变化?
【发布时间】:2021-02-08 23:21:42
【问题描述】:

目标是当 LookAndFeel 在 main 方法中时改变所有组合框的背景。 但是当 LookAndFeel 存在和不存在时,我会得到不同的结果。

没有 LookAndFeel: JComboBox 在 JFrame 调整大小后可见

import javax.swing.*;
import java.awt.*;

import static java.awt.Color.WHITE;

public class TestFrame extends JFrame {

    private static final String[] ANIMALS = new String[]{"Cat", "Mouse", "Dog", "Elephant", "Bird", "Goat", "Bear"};

    public TestFrame() {
        setSize(600, 300);
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        JPanel panel = new JPanel();
        JComboBox<String> comboBox = new JComboBox<>();
        comboBox.setModel(new DefaultComboBoxModel<>(ANIMALS));
        comboBox.setForeground(WHITE);
        comboBox.setBackground(new Color(71, 81, 93));
        comboBox.getEditor().getEditorComponent().setBackground(new Color(71, 81, 93));
        comboBox.getEditor().getEditorComponent().setForeground(WHITE);
        comboBox.setRenderer(new DefaultListCellRenderer() {
            @Override
            public void paint(Graphics g) {
                setBackground(new Color(71, 81, 93));
                setForeground(WHITE);
                super.paint(g);
            }
        });
        panel.add(comboBox);
        add(panel);
    }

    public static void main(String[] args) {
        new TestFrame();
    }
}

使用 LookAndFeel:

import javax.swing.*;
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;

import static java.awt.Color.WHITE;

public class TestFrame extends JFrame {

    private static final String[] ANIMALS = new String[]{"Cat", "Mouse", "Dog", "Elephant", "Bird", "Goat", "Bear"};

    public TestFrame() {
        setSize(600, 300);
        setVisible(true);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        JPanel panel = new JPanel();
        JComboBox<String> comboBox = new JComboBox<>();
        comboBox.setModel(new DefaultComboBoxModel<>(ANIMALS));
        comboBox.setForeground(WHITE);
        comboBox.setBackground(new Color(71, 81, 93));
        comboBox.getEditor().getEditorComponent().setBackground(new Color(71, 81, 93));
        comboBox.getEditor().getEditorComponent().setForeground(WHITE);
        comboBox.setRenderer(new DefaultListCellRenderer() {
            @Override
            public void paint(Graphics g) {
                setBackground(new Color(71, 81, 93));
                setForeground(WHITE);
                super.paint(g);
            }
        });
        panel.add(comboBox);
        add(panel);
    }

    public static void main(String[] args) {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            Logger.getLogger(TestFrame.class.getName()).log(Level.SEVERE, null, ex);
        }

        /* Create and display the form */
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new TestFrame();
            }
        });
    }
}

如何在启用 LookAndFeel 的情况下实现组合框的完整绘制?

【问题讨论】:

    标签: java swing jcombobox look-and-feel


    【解决方案1】:

    没有像禁用或启用LookAndFeel 这样的东西。您始终在应用程序中设置外观。您似乎只是设置了另一个LookAndFeel,在您的情况下是Nimbus。但是,为了回答您的问题,NimbusDefaultListCellRenderer 的不透明度属性设置为false,(例如MetalLookAndFeel 将其设置为true),这是视觉效果的原因您正在展示的代表。您应该可以通过覆盖DefaultListCellRenderergetListCellRendererComponent 方法来解决此问题,如下所示:

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
                            int index, boolean isSelected, boolean cellHasFocus) {
    
        JComponent comp = (JComponent) super.getListCellRendererComponent(list,
                    value, index, isSelected, cellHasFocus);
    
        list.setBackground(COMBO_COLOR);
        list.setForeground(Color.WHITE);
        list.setOpaque(false);
            
        return comp;
    }
    

    您还必须将 UIManagers 属性 ComboBox.forceOpaque 设置为 false,如下所示:

    UIManager.put("ComboBox.forceOpaque", false);
    

    Nimubs 默认值的完整列表可以在here 找到。

    如果需要,提供已解决问题的完整工作示例:

    import java.awt.*;
    import java.util.Arrays;
    import javax.swing.*;
    
    public class JComboBoxExample {
        
        private static final Color COMBO_COLOR = new Color(71, 81, 93);
        private static final String[] COMBO_DATA = {"Get back!", "Go!", "Help!", "Careful!"};
        
        public static void main(String[] args) throws Exception {        
            String nimbus = Arrays.asList(UIManager.getInstalledLookAndFeels())
                    .stream()
                    .filter(i -> i.getName().equals("Nimbus"))
                    .findFirst()
                    .get()
                    .getClassName();
            
            UIManager.setLookAndFeel(nimbus);
            
            UIManager.put("ComboBox.forceOpaque", false);
            
            JFrame jf = new JFrame();
            jf.setVisible(true);
            jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jf.setLocationRelativeTo(null);
            
            MyComboBox comboBox = new MyComboBox(new DefaultComboBoxModel(COMBO_DATA));
            jf.add(comboBox);
            jf.pack();
        }
        
        private static class MyComboBox extends JComboBox  {
    
            public MyComboBox(DefaultComboBoxModel model) {
                super(model);
                setForeground(Color.WHITE);
                setFont(new Font("Arial", Font.PLAIN, 30));
                setPreferredSize(new Dimension(350, 50));
                setRenderer(new MyRenderer());
            }
    
        }
    
        private static class MyRenderer extends DefaultListCellRenderer {
            
            @Override
            public Component getListCellRendererComponent(JList list, Object value,
                                int index, boolean isSelected, boolean cellHasFocus) {
    
                JComponent comp = (JComponent) super.getListCellRendererComponent(list,
                        value, index, isSelected, cellHasFocus);
    
                list.setBackground(COMBO_COLOR);
                list.setForeground(Color.WHITE);
                list.setOpaque(false);
                
                return comp;
            }
        }
        
    }
    

    结果:

    顺便说一句,我使用 NetBeans IDE 的可视化调试器解决了这个问题。

    【讨论】:

    • 很好,没问题:)
    • 莫里茨,我忘了问一件小事。是否有可能摆脱“Get Back!”之间的这条白色垂直线?和向下箭头按钮?还有一件事是,当您将鼠标悬停在元素上时,现在元素不会突出显示。其他都很好)
    • @Neo,我更新了我的答案。悬停现在应该也可以了。您应该针对您所描述的小垂直线打开一个新问题。
    • @Neo 我找到了解决问题的办法。随时提出问题(使用您的代码,您尝试了什么......)。
    • 谢谢,很高兴听到这个消息。我创建了新问题stackoverflow.com/questions/64578854/…
    猜你喜欢
    • 2021-02-08
    • 1970-01-01
    • 1970-01-01
    • 2015-09-03
    • 2014-01-25
    • 2014-07-24
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    相关资源
    最近更新 更多