1

我正在尝试将 JButton 用作 JComboBox 中的编辑器。在 Mac OS X 上这看起来不错,但在使用系统外观的 Windows 上,JButton 编辑器和组合按钮本身之间留下了一个难看的差距:

显示 JButton 和组合按钮之间间隙的图像

这是用于生成对话框的测试代码:

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

import javax.swing.*;


public class ButtonEditorTest implements Runnable {

    String[] items = {"One", "Two", "Three"};

    ComboBoxModel model;

    ButtonEditorTest() {
        // our model, kept simple for the test
        model = new DefaultComboBoxModel(items);

        // create the UI on the EDT
        SwingUtilities.invokeLater(this);
    }

    // creates UI on the event dispatch thread
    @Override
    public void run() {
        JComboBox comboBox = new JComboBox(model);
        comboBox.setEditable(true);
        comboBox.setEditor(new ComboButtonEditor());

        JFrame frame = new JFrame("JComboBox with JButton editor test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(comboBox, BorderLayout.NORTH);
        frame.setSize(200, 100);
        frame.setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        String lookAndFeelClassName = UIManager.getSystemLookAndFeelClassName();
        UIManager.setLookAndFeel(lookAndFeelClassName);
        new ButtonEditorTest();
    }


    class ComboButtonEditor implements ComboBoxEditor {

        private JButton button = new JButton();
        private Object item;

        @Override
        public void addActionListener(ActionListener arg0) {
            // not needed for UI test
        }

        @Override
        public Component getEditorComponent() {
            return button;
        }

        @Override
        public Object getItem() {
            return item;
        }

        @Override
        public void removeActionListener(ActionListener arg0) {
            // not needed for UI test
        }

        @Override
        public void selectAll() {
            // not needed for UI test
        }

        @Override
        public void setItem(Object item) {
            this.item = item;
            button.setText(item.toString());
        }

    }
}
4

2 回答 2

2

由于某种原因,Window LAF 覆盖了按钮的默认布局。这导致按钮变窄。但是,编辑器的宽度没有增加以考虑较窄的按钮,因此出现了间隙。这是来自 WindowsComboBoxUI 的代码:

protected LayoutManager createLayoutManager() {
    return new BasicComboBoxUI.ComboBoxLayoutManager() {
    public void layoutContainer(Container parent) {
    super.layoutContainer(parent);

    if (XPStyle.getXP() != null && arrowButton != null) {
        Dimension d = parent.getSize();
        Insets insets = getInsets();
        int buttonWidth = arrowButton.getPreferredSize().width;
        arrowButton.setBounds(WindowsGraphicsUtils.isLeftToRight((JComboBox)parent)
      ? (d.width - insets.right - buttonWidth)
      : insets.left,
      insets.top,
      buttonWidth, d.height - insets.top - insets.bottom);
    }
    }
};
}

更好的布局可能是这样的:

comboBox.setUI( new WindowsComboBoxUI()
{
    @Override
    protected LayoutManager createLayoutManager()
    {
        return new BasicComboBoxUI.ComboBoxLayoutManager()
        {
            public void layoutContainer(Container parent)
            {
                super.layoutContainer(parent);

                System.out.println(editor.getBounds());
                System.out.println(arrowButton.getBounds());

//              if (XPStyle.getXP() != null && arrowButton != null)
//              {
                    Dimension d = parent.getSize();
                    Insets insets = getInsets();
                    int buttonWidth = arrowButton.getPreferredSize().width;
                    boolean isLeftToRight = parent.getComponentOrientation().isLeftToRight();

                    arrowButton.setBounds(isLeftToRight
                    ? (d.width - insets.right - buttonWidth)
                    : insets.left, insets.top, buttonWidth, d.height - insets.top - insets.bottom);

                    System.out.println(editor.getBounds());
                    System.out.println(arrowButton.getBounds());

                    Dimension size = editor.getSize();
                    editor.setSize(arrowButton.getLocation().x - 1, size.height);
//              }

            }
        };
    }
});

我添加了一些输出来显示编辑器宽度在 XP 调整之前/之后如何变化。另外我不知道如何检查 XP LAF,因为 XPStyle 类不是公开的。

LAF的进口:

import javax.swing.plaf.basic.*;
import com.sun.java.swing.plaf.windows.*;
于 2010-10-22T05:29:29.507 回答
0

我认为如果您将添加到的 BorderLayout 的位置更改为 CENTER,如下所示:

frame.getContentPane().add(comboBox, BorderLayout.CENTER);

它将解决该问题。虽然按钮可能会变大一点,但如果需要,您可以通过重新调整大小值来解决这个问题。

于 2010-10-22T02:06:42.643 回答