【问题标题】:Alignment resets when using setEditable() for a JComboBox对 JComboBox 使用 setEditable() 时对齐重置
【发布时间】:2015-10-25 12:12:40
【问题描述】:
class RuleComboBox extends JComboBox {

    public RuleComboBox() {
        super();
        this.setModel(new javax.swing.DefaultComboBoxModel(new String[]{"abc", "defg"}));
        ((JLabel) this.getRenderer()).setHorizontalAlignment(SwingConstants.CENTER);
    }

}

getRenderer() 行使文本居中对齐。

当我使用ruleComboBox1.setEnabled(false)ruleComboBox1.setEditable(true) 时,文本会回到我不想要的左侧。我怎样才能阻止这种情况?

我应该解释一下,当我禁用它时,我使用setEditable(true) 来保持ComboBox 内的文本外观。

【问题讨论】:

    标签: java swing alignment jcombobox listcellrenderer


    【解决方案1】:

    JComboBox 的编辑器必须实现 ComboBoxEditor 接口。默认实现扩展自BasicComboBoxEditor,它返回一个 JTextField 作为编辑器。 JTextField 不支持文本居中显示的概念。

    因此您可以实现自己的ComboBoxEditor。我建议您可以只使用BasicComboBoxEditor 并更改代码以创建JTextPane 而不是JTextField。然后,当您创建文本窗格时,您可以使用:

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

    这将导致代码居中。

    注意:这不是直接的转换。当按下Enter 键时,JTextField 调用ActionListener。 JTextPane 不支持此功能(默认为插入新行),因此您需要为 JTextPane 复制此功能。也就是说,您将需要使用 Key Bindings 来处理 Enter 键。因此,您需要将 ActionListener 包装在自定义 Action 中,然后将 Enter 键绑定到文本窗格。

    import javax.swing.*;
    import javax.swing.text.*;
    import javax.swing.border.Border;
    import java.awt.Component;
    import java.awt.event.*;
    
    import java.lang.reflect.Method;
    //import sun.reflect.misc.MethodUtil;
    
    /**
     * A custom editor for editable combo boxes. The editor is implemented as a JTextPane.
     *
     */
    public 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);
            }
        }
    }
    

    您当前的代码只需要:

    comboBox.setEditor( new TextPaneComboBoxEditor() );
    

    【讨论】:

      猜你喜欢
      • 2015-02-15
      • 2018-01-10
      • 2015-11-05
      • 1970-01-01
      • 2021-07-29
      • 2015-08-15
      • 1970-01-01
      • 2020-12-06
      • 1970-01-01
      相关资源
      最近更新 更多