java - JComboBox 中的项目居中,并且在禁用时清晰地显示文本

标签 java swing jcombobox

我正在使用

((JLabel)comboBox.getRenderer()).setHorizo​​ntalAlignment(SwingConstants.CENTER);

将我的 JComboBox 中的文本项居中。

但我也希望在禁用 ComboBox 时文本能够清晰显示(即文本外观不应/几乎不改变)。

解决方案是当我使用 comboBox.setVisible(false) 时使用 comboBox.setEditable(true) (有关更多信息,请参见下文),除了对齐之外效果很好文本回到左侧。看来解决这个问题需要做很多工作。

我想知道是否有人可以建议另一种方法来在禁用的comboBox中清晰地显示文本?

非常感谢。

编辑:我用来改进禁用文本显示的完整代码是

        ComboBoxEditor editor = comboBox.getEditor();
        JTextField etf = (JTextField) editor.getEditorComponent();
        etf.setDisabledTextColor(UIManager.getColor("ComboBox.foreground"));
        etf.setBackground(UIManager.getColor("ComboBox.background"));
        comboBox.setEnabled(false);
        comboBox.setEditable(true);

编辑 2:

这是一个完整的示例:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;


public class GUITest extends JPanel {

    static JFrame frame;
    static JButton changeButton;
    static JComboBox exampleComboBox;

    public GUITest() {
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        String[] examples = {
            "abcd",
            "efgh",
            "ij"
        };

        exampleComboBox = new JComboBox(examples);

        // centre text of items in combo box
        ((JLabel) exampleComboBox.getRenderer()).setHorizontalAlignment(SwingConstants.CENTER);

        JLabel buttonLabel = new JLabel("Click to make combo box disabled but text show clearly",
                JLabel.LEADING); //== LEFT

        JPanel patternPanel = new JPanel();
        patternPanel.setLayout(new BoxLayout(patternPanel,
                BoxLayout.PAGE_AXIS));

        exampleComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
        patternPanel.add(exampleComboBox);

        JPanel resultPanel = new JPanel(new GridLayout(0, 1));
        resultPanel.add(buttonLabel);
        changeButton = new JButton();
        resultPanel.add(changeButton);
        addButtonListener();

        patternPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
        resultPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

        add(patternPanel);
        add(Box.createRigidArea(new Dimension(0, 10)));
        add(resultPanel);

        setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

    } //constructor

    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("ComboBoxDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new GUITest();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    private static void addButtonListener() {
        changeButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                ComboBoxEditor editor = exampleComboBox.getEditor();
                JTextField etf = (JTextField) editor.getEditorComponent();
                etf.setDisabledTextColor(UIManager.getColor("ComboBox.foreground"));
                etf.setBackground(UIManager.getColor("ComboBox.background"));
                exampleComboBox.setEnabled(false);
                exampleComboBox.setEditable(true);
            }
        });
    }

    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

编辑 3:现在可以运行,但文本会稍微向上移动,并且单击按钮时组合框边框会被删除。有没有办法防止这种情况发生?

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;


public class GUITest extends JPanel {

    static JFrame frame;
    static JButton changeButton;
    static JComboBox exampleComboBox;

    public GUITest() {
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        String[] examples = {
            "abcd",
            "efgh",
            "ij"
        };

        exampleComboBox = new JComboBox(examples);
        exampleComboBox.setEditor(new TextPaneComboBoxEditor());

        // centre text of items in combo box
        ((JLabel) exampleComboBox.getRenderer()).setHorizontalAlignment(SwingConstants.CENTER);

        JLabel buttonLabel = new JLabel("Click to make combo box disabled but text show clearly",
                JLabel.LEADING); //== LEFT

        JPanel patternPanel = new JPanel();
        patternPanel.setLayout(new BoxLayout(patternPanel,
                BoxLayout.PAGE_AXIS));

        exampleComboBox.setAlignmentX(Component.LEFT_ALIGNMENT);
        patternPanel.add(exampleComboBox);

        JPanel resultPanel = new JPanel(new GridLayout(0, 1));
        resultPanel.add(buttonLabel);
        changeButton = new JButton();
        resultPanel.add(changeButton);
        addButtonListener();

        patternPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
        resultPanel.setAlignmentX(Component.LEFT_ALIGNMENT);

        add(patternPanel);
        add(Box.createRigidArea(new Dimension(0, 10)));
        add(resultPanel);

        setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

    } //constructor

    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("ComboBoxDemo2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        JComponent newContentPane = new GUITest();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    private static void addButtonListener() {
        changeButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                ComboBoxEditor editor = exampleComboBox.getEditor();
                JTextPane etf = (JTextPane) editor.getEditorComponent();
                etf.setDisabledTextColor(UIManager.getColor("ComboBox.foreground"));
                etf.setBackground(UIManager.getColor("ComboBox.background"));
                exampleComboBox.setEnabled(false);
                exampleComboBox.setEditable(true);
            }
        });
    }

    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

class TextPaneComboBoxEditor implements ComboBoxEditor {
    protected JTextPane editor;
    private Object oldValue;

    public TextPaneComboBoxEditor() {
        editor = createEditorComponent();
    }

    public Component getEditorComponent() {
        return editor;
    }

    /**
     * Creates the internal editor component. Override this to provide
     * a custom implementation.
     *
     * @return a new editor component
     * @since 1.6
     */
    protected JTextPane createEditorComponent() {
        JTextPane editor = new BorderlessTextPane("",9);
        editor.setBorder(null);

        SimpleAttributeSet center = new SimpleAttributeSet();
        StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
        StyledDocument doc = editor.getStyledDocument();
        doc.setParagraphAttributes(0, doc.getLength(), center, false);

        return editor;
    }

    /**
     * Sets the item that should be edited.
     *
     * @param anObject the displayed value of the editor
     */
    public void setItem(Object anObject) {
        String text;

        if ( anObject != null )  {
            text = anObject.toString();
            if (text == null) {
                text = "";
            }
            oldValue = anObject;
        } else {
            text = "";
        }

        // workaround for 4530952
        if (! text.equals(editor.getText())) {
            editor.setText(text);
        }

    }

    public Object getItem() {
        Object newValue = editor.getText();

        // This code only works for Strings. The default implementation would
        // use reflection to create Object of whatever class was stored in the
        // ComboBoxModel. You will need to fix the reflection code if you want
        // to support other types of data in the model

/*
        if (oldValue != null && !(oldValue instanceof String))  {
            // The original value is not a string. Should return the value in it's
            // original type.
            if (newValue.equals(oldValue.toString()))  {
                return oldValue;
            } else {
                // Must take the value from the editor and get the value and cast it to the new type.
                Class<?> cls = oldValue.getClass();
                try {
                    Method method = MethodUtil.getMethod(cls, "valueOf", new Class[]{String.class});
                    newValue = MethodUtil.invoke(method, oldValue, new Object[] { editor.getText()});
                } catch (Exception ex) {
                    // Fail silently and return the newValue (a String object)
                }
            }
        }
*/
        return newValue;
    }

    public void selectAll() {
        editor.selectAll();
        editor.requestFocus();
    }

    public void addActionListener(ActionListener l) {
//        editor.addActionListener(l);

        Action enter = new WrappedActionListener(l);
        editor.getActionMap().put("insert-break", enter);
    }

    public void removeActionListener(ActionListener l) {
//        editor.removeActionListener(l);
    }

    static class BorderlessTextPane extends JTextPane {
        public BorderlessTextPane(String value,int n) {
//            super(value,n);
            setText(value);
        }

        // workaround for 4530952
        public void setText(String s) {
            if (getText().equals(s)) {
                return;
            }
            super.setText(s);
        }

        public void setBorder(Border b) {
            if (!(b instanceof UIResource)) {
                super.setBorder(b);
            }
        }
    }

    /**
     * A subclass of TextPaneComboBoxEditor that implements UIResource.
     * TextPaneComboBoxEditor doesn't implement UIResource
     * directly so that applications can safely override the
     * cellRenderer property with TextPaneListCellRenderer subclasses.
     * <p>
     * <strong>Warning:</strong>
     * Serialized objects of this class will not be compatible with
     * future Swing releases. The current serialization support is
     * appropriate for short term storage or RMI between applications running
     * the same version of Swing.  As of 1.4, support for long term storage
     * of all JavaBeans&trade;
     * has been added to the <code>java.beans</code> package.
     * Please see {@link java.beans.XMLEncoder}.
     */
    public static class UIResource extends TextPaneComboBoxEditor
    implements javax.swing.plaf.UIResource {
    }

    static class WrappedActionListener extends AbstractAction
    {
        private ActionListener listener;

        public WrappedActionListener(ActionListener listener)
        {
            this.listener = listener;
        }

        @Override
        public void actionPerformed(ActionEvent e)
        {
            listener.actionPerformed(e);
        }
    }
}

最佳答案

禁用组合框后,无需使用编辑器。只需禁用组合框即可。所以ActionListener中的代码是:

changeButton.addActionListener(new ActionListener() 
{
    @Override
    public void actionPerformed(ActionEvent e) 
    {
        exampleComboBox.setEnabled(false);
        //exampleComboBox.setEditable(true);
    }
});

然后在类(class)顶部,您可以使用:

UIManager.put("ComboBox.disabledForeground", Color.BLACK);

查看禁用组合框使用的前景色。当组合框被禁用时,编辑器不会显示,因此正常渲染已完成。

所以你不需要使用JTextPane作为编辑器。

关于java - JComboBox 中的项目居中,并且在禁用时清晰地显示文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31859384/

相关文章:

java - 如何获得登录我的网络应用程序的所有用户的列表

java - SwingWorker:取消工作线程后调用done()时抛出错误

java - JTable 数据未在组合框选择上更新(数据来自文件)

java - 更新 JCombobox 始终给出第一个元素 EMPTY

java - Play Framework 部署失败

java - 避免 isInstance 语句

java - 如何重新绘制 JFrame 以更新变量值?

Java:如何在不使用 actionListener 的情况下检测到用户已经完成了他们的保存名称?

java - 为什么我的所有组件都聚集在 JFrame 的中心

java - jComboBox 与隐藏数据 java