在Windows L& F中使用JButton作为ComboBoxEditor时如何消除差距?

时间:2010-10-22 01:17:05

标签: java windows swing jbutton jcombobox

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

image showing gap between JButton and combo button

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

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

    }
}

2 个答案:

答案 0 :(得分: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.*;

答案 1 :(得分:0)

我想如果你改变你添加到的BorderLayout的位置,就像这样:

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

它将解决这个问题。 虽然按钮可能会变大,但您可以通过在必要时重新调整大小值来解决这个问题。