Java Swing - Motif L&F 中自定义组合框渲染器中的文本消失

标签 java swing jcombobox listcellrenderer motif

我目前正在为 JComboBox 编写自定义 ListCellRenderer。为此,我使用一个系统在 L&F 更改时获取新的渲染器,并将方法委托(delegate)给它。这在所有 L&F 中都很有效。但是,当我将此组件放置在面板中(以便我可以添加更多组件)时,它在 Metal 和 Windows L&F 中运行良好,但 JComboBox 文本在 Motif 中消失。查看截图和代码:

Problem with the third renderer

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class TextDemo extends JPanel implements ActionListener {

    private static JFrame frame;

    public TextDemo() {
        super(new GridBagLayout());

        JComboBox correct = new JComboBox(new String[]{"One", "Two", "Three"});

        JComboBox alsoCorrect = new JComboBox(new String[]{"One", "Two", "Three"});
        alsoCorrect.setRenderer(new MyRenderer());

        JComboBox incorrect = new JComboBox(new String[]{"One", "Two", "Three"});
        incorrect.setRenderer(new NotWorkingRenderer());

        JButton button = new JButton("Change LnF");
        button.addActionListener(this);

        add(correct, getConstraints(0));
        add(alsoCorrect, getConstraints(1));
        add(incorrect, getConstraints(2));
        add(button, getConstraints(3));
    }

    private GridBagConstraints getConstraints(int y) {
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0; c.gridy = y;
        c.insets = new Insets(4,8,4,8);
        c.weightx = 1.0; c.weighty = 1.0;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        return c;
    }

    @Override
    public void actionPerformed(ActionEvent ev) {
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
            SwingUtilities.updateComponentTreeUI(frame);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static void createAndShowGUI() {
        frame = new JFrame("TextDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TextDemo());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

class MyRenderer implements ListCellRenderer {
    protected static ListCellRenderer delegate;
    static {
        refreshRenderers();
        UIManager.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals("lookAndFeel")) {
                    refreshRenderers();
                }
            }
        });
    }
    protected static void refreshRenderers() {
        delegate = new JComboBox().getRenderer();
    }
    @Override
    public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {
        return delegate.getListCellRendererComponent(list, value,
                index, isSelected, cellHasFocus);
    }
}

class NotWorkingRenderer extends MyRenderer {
    private JPanel panel = new JPanel();
    public NotWorkingRenderer() {
        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
    }
    @Override
    public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {
        Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        c.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
                    panel.removeAll();
        panel.add(c);
        return panel;
    }
}

任何有关理解为什么会发生这种情况的帮助将不胜感激!

最佳答案

不是答案,

  • 但是看看会发生什么,使用 JPanel 作为 JComboBox 的渲染器 JComponent

  • 您确定使用字符串值的 JPanel 是正确的方法吗?请问目标是什么,

  • 用默认的JLabel、(J)Component代替JPanel是否有同样的效果

enter image description here enter image description here enter image description here

来自代码

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.*;

public class TextDemo extends JPanel implements ActionListener {

    private static JFrame frame;

    public TextDemo() {
        super(new GridBagLayout());
        JComboBox correct = new JComboBox(new String[]{"One", "Two", "Three"});
        JComboBox alsoCorrect = new JComboBox(new String[]{"One", "Two", "Three"});
        alsoCorrect.setRenderer(new MyRenderer());
        JComboBox incorrect = new JComboBox(new String[]{"One", "Two", "Three"});
        incorrect.setRenderer(new NotWorkingRenderer());
        JButton button = new JButton("Change LnF");
        button.addActionListener(this);
        add(incorrect, getConstraints(0));
        add(correct, getConstraints(1));
        add(alsoCorrect, getConstraints(2));
        add(button, getConstraints(3));
    }

    private GridBagConstraints getConstraints(int y) {
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = y;
        c.insets = new Insets(4, 8, 4, 8);
        c.weightx = 1.0;
        c.weighty = 1.0;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.FIRST_LINE_START;
        return c;
    }

    @Override
    public void actionPerformed(ActionEvent ev) {
        try {
            UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
            SwingUtilities.updateComponentTreeUI(frame);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static void createAndShowGUI() {
        frame = new JFrame("TextDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TextDemo());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
            //SwingUtilities.updateComponentTreeUI(frame);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

class MyRenderer implements ListCellRenderer {

    protected static ListCellRenderer delegate;

    static {
        refreshRenderers();
        UIManager.addPropertyChangeListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName().equals("lookAndFeel")) {
                    refreshRenderers();
                }
            }
        });
    }

    protected static void refreshRenderers() {
        delegate = new JComboBox().getRenderer();
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {
        return delegate.getListCellRendererComponent(list, value,
                index, isSelected, cellHasFocus);
    }
}

class NotWorkingRenderer extends MyRenderer {

    private JPanel panel = new JPanel();

    public NotWorkingRenderer() {
        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {
        Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        c.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));
        panel.add(c);
        return panel;
    }
}

EDIT_1。

  • 除 ModifL&F 之外的所有标准 L&F 均正确显示

  • 向前迈出一步???,代码行in Correct.setEditable(true);生成

enter image description here

  • 我不知道 ModifL&F 和 non_editable JComboBox 的正确方法

EDIT_2nd。

  • 我瞎了class NotWorkingRenderer extends MyRenderer {, pip... pip... pip...

  • phaaa 我从未添加/删除/修改 JComponentXxx(Xxx)Renderer中,但是是关于是否可能,

enter image description here

class NotWorkingRenderer extends BasicComboBoxRenderer {

    private JPanel panel = new JPanel();

    public NotWorkingRenderer() {
        panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
        //panel.setOpaque(false);
    }

    @Override
    public Component getListCellRendererComponent(JList list, Object value,
            int index, boolean isSelected, boolean cellHasFocus) {
        JLabel c = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        c.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));        
        panel.removeAll();
        panel.add(c);
        panel.revalidate();
        panel.repaint();
        return panel;
    }
}

关于Java Swing - Motif L&F 中自定义组合框渲染器中的文本消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18536082/

相关文章:

java - 鼠标监听器和鼠标点击

java - 从数据库中获取值后如何清除 jComboBox

java - 从字符串设置所选项目 JComboBox

java - JCombobox 意外行为

Java 游戏无法运行

java - JxBrowser 卡住整个应用程序

java - 当您更新一个集合(即映射中的值),然后将键和值放入映射中时,是否会创建重复项?

java - 我试图让球逐渐移动

java - eclipse RCP : Why is the view missing when running as a Product?

java - 神经网络输入建议