外观阻止了JComboBox的背景更改?

huangapple go评论76阅读模式
英文:

LookAndFeel blocking JComboBox background change?

问题

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


<details>
<summary>英文:</summary>
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.
**Without LookAndFeel:** JComboBox is visible after JFrame resizing
[![enter image description here][1]][1]

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

import static java.awt.Color.WHITE;

public class TestFrame extends JFrame {

private static final String[] ANIMALS = new String[]{&quot;Cat&quot;, &quot;Mouse&quot;, &quot;Dog&quot;, &quot;Elephant&quot;, &quot;Bird&quot;, &quot;Goat&quot;, &quot;Bear&quot;};
public TestFrame() {
setSize(600, 300);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JComboBox&lt;String&gt; comboBox = new JComboBox&lt;&gt;();
comboBox.setModel(new DefaultComboBoxModel&lt;&gt;(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();
}

}


**With LookAndFeel:**
[![enter image description here][2]][2]

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[]{&quot;Cat&quot;, &quot;Mouse&quot;, &quot;Dog&quot;, &quot;Elephant&quot;, &quot;Bird&quot;, &quot;Goat&quot;, &quot;Bear&quot;};
public TestFrame() {
setSize(600, 300);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JComboBox&lt;String&gt; comboBox = new JComboBox&lt;&gt;();
comboBox.setModel(new DefaultComboBoxModel&lt;&gt;(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 (&quot;Nimbus&quot;.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();
}
});
}

}


How can I achieve full painting of the combo box with LookAndFeel enabled?
[1]: https://i.stack.imgur.com/0hGcf.png
[2]: https://i.stack.imgur.com/dWYUu.png
</details>
# 答案1
**得分**: 1
这里没有"禁用"或"启用"的`LookAndFeel`。您的应用程序中始终设置了一个外观。您似乎只是设置了另一个外观,而在您的情况下是**Nimbus**。然而,为了回答您的问题,**Nimbus**将`DefaultListCellRenderer`的不透明性属性设置为`false`(例如,`MetalLookAndFeel`将其设置为`true`),这就是您所展示的可视化表示的原因。您可以通过重写`DefaultListCellRenderer`的`getListCellRendererComponent`方法来解决这个问题,代码如下:
```java
@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);

Nimbus的完整默认列表可以在此处找到。

如果需要,以下是修复问题的完整示例代码:

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;
        }
    }
    
}

运行结果如下:

外观阻止了JComboBox的背景更改?

顺便提一下,我通过使用NetBeans IDE的可视化调试器找到了这个解决方案。

英文:

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;
}

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

UIManager.put(&quot;ComboBox.forceOpaque&quot;, false);

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 = {&quot;Get back!&quot;, &quot;Go!&quot;, &quot;Help!&quot;, &quot;Careful!&quot;};
public static void main(String[] args) throws Exception {        
String nimbus = Arrays.asList(UIManager.getInstalledLookAndFeels())
.stream()
.filter(i -&gt; i.getName().equals(&quot;Nimbus&quot;))
.findFirst()
.get()
.getClassName();
UIManager.setLookAndFeel(nimbus);
UIManager.put(&quot;ComboBox.forceOpaque&quot;, 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(&quot;Arial&quot;, 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;
}
}
}

results in:

外观阻止了JComboBox的背景更改?

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

huangapple
  • 本文由 发表于 2020年10月27日 00:55:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/64541587.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定