LookAndFeel阻止JComboBox的背景改变了吗? [英] LookAndFeel blocking JComboBox background change?

查看:70
本文介绍了LookAndFeel阻止JComboBox的背景改变了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标是在主方法中使用LookAndFeel时更改所有组合框的背景. 但是当LookAndFeel存在和不存在时,我得到的结果都是不同的.

The goal is to change the background of all combo box when LookAndFeel is in the main method. But I get different results when LookAndFeel exists and not.

不使用LookAndFeel:调整JFrame的大小后,即可看到JComboBox

Without LookAndFeel: JComboBox is visible after JFrame resizing

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的情况下实现组合框的完整绘制?

How can I achieve full painting of the combo box with LookAndFeel enabled?

推荐答案

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

There is no thing like a disabled or enabled LookAndFeel. You always have a Look and feel set in your aplication. You just seem to set another LookAndFeel, which in your case is Nimbus. However, to answer your question, Nimbus sets the DefaultListCellRenderer's opacity-Property to false, (MetalLookAndFeel for example sets it to true) which is the reason for the visual representation you are showing. You should be able to fix this by overriding the getListCellRendererComponent method of DefaultListCellRenderer like so:

@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,如下所示:

You also have to set the UIManagers property ComboBox.forceOpaque to false, like so:

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

Nimubs defauts的完整列表可以找到此处.

A full list of the Nimubs defauts can be found here.

如有需要,可提供已解决问题的完整示例:

A full working example of the fixed problem if needed:

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 的可视调试器解决了这一问题.

By the way, I figured this out by using the visual debugger of the NetBeans IDE.

这篇关于LookAndFeel阻止JComboBox的背景改变了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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