【问题标题】:JComboBox does not behave same as JTextField. How can i have it look similar?JComboBox 的行为与 JTextField 不同。我怎样才能让它看起来相似?
【发布时间】:2012-04-16 05:17:10
【问题描述】:

我有以下组合框,我可以在其中创建包含项目等的组合框,但外观与 JTextField 不同。如何让 JCombobox 看起来像 JTextField?

MyComboBox.java:

import java.awt.Color;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.plaf.basic.BasicComboBoxUI;

public class MyComboBox extends JComboBox {
  public MyComboBox(String[] name) {
    Border border = BorderFactory.createEmptyBorder(11, 11, 11, 11);
    JComboBox cb = new JComboBox(name);
    cb.setUI(new BasicComboBoxUI() {
        @Override
        protected JButton createArrowButton() {
            return new JButton() {
                    @Override
                    public int getWidth() {
                            return 0;
                    }
            };
        }
    });

    setModel(cb.getModel());    
    setOpaque(false);
    setBorder(new LineBorder(Color.black, 1, true));
    //setBackground(Color.white);
    setVisible(true); 


  }
//  public void paintComponent(Graphics g) {
//      super.paintComponent(g);                
//      g.setColor(new Color(red, green, blue) );
//      g.fillOval(125, 125, 50, 50);
//  }  
}

【问题讨论】:

    标签: java swing user-interface jcombobox jtextfield


    【解决方案1】:
    • 最好是使用Look and Feels

    • JComboBox有两种状态,JComboBox可以是EditableNon_Editable(默认)

    • 没有CustomUI(以@aterai 为例),但Look and Feel 敏感,仅适用于Metal Look and Feel

    import java.awt.*;
    import java.util.Vector;
    import javax.swing.*;
    import javax.swing.UIManager;
    import javax.swing.plaf.ColorUIResource;
    import javax.swing.plaf.metal.MetalComboBoxButton;
    
    public class MyComboBox {
    
        private Vector<String> listSomeString = new Vector<String>();
        private JComboBox someComboBox = new JComboBox(listSomeString);
        private JComboBox editableComboBox = new JComboBox(listSomeString);
        private JComboBox non_EditableComboBox = new JComboBox(listSomeString);
        private JFrame frame;
    
        public MyComboBox() {
            listSomeString.add("-");
            listSomeString.add("Snowboarding");
            listSomeString.add("Rowing");
            listSomeString.add("Knitting");
            listSomeString.add("Speed reading");
    //
            someComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            someComboBox.setFont(new Font("Serif", Font.BOLD, 16));
            someComboBox.setEditable(true);
            someComboBox.getEditor().getEditorComponent().setBackground(Color.YELLOW);
            ((JTextField) someComboBox.getEditor().getEditorComponent()).setBackground(Color.YELLOW);
    //        
            editableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            editableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
            editableComboBox.setEditable(true);
            JTextField text = ((JTextField) editableComboBox.getEditor().getEditorComponent());
            text.setBackground(Color.YELLOW);
            JComboBox coloredArrowsCombo = editableComboBox;
            Component[] comp = coloredArrowsCombo.getComponents();
            for (int i = 0; i < comp.length; i++) {
                if (comp[i] instanceof MetalComboBoxButton) {
                    MetalComboBoxButton coloredArrowsButton = (MetalComboBoxButton) comp[i];
                    coloredArrowsButton.setBackground(null);
                    break;
                }
            }
    //        
            non_EditableComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            non_EditableComboBox.setFont(new Font("Serif", Font.BOLD, 16));
    //
            frame = new JFrame();
            frame.setLayout(new GridLayout(0, 1, 10, 10));
            frame.add(someComboBox);
            frame.add(editableComboBox);
            frame.add(non_EditableComboBox);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLocation(100, 100);
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            UIManager.put("ComboBox.background", new ColorUIResource(Color.yellow));
            UIManager.put("JTextField.background", new ColorUIResource(Color.yellow));
            UIManager.put("ComboBox.selectionBackground", new ColorUIResource(Color.magenta));
            UIManager.put("ComboBox.selectionForeground", new ColorUIResource(Color.blue));
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    MyComboBox aCTF = new MyComboBox();
                }
            });
        }
    }
    

    【讨论】:

    • @aterai 请问有另一种方法如何从 JComboBox 获取/放置 BasicButtonUI(另一种在你的好例子中)
    • 你打赌! “JComboBox 的行为与 JTextField 不同”听起来像“正在寻找可编辑的 JComboBox”。
    • @aterai 不是,错了,我不是,为什么???,因为真的不知道如何解决,疯狂的 AbstractButton,eeerrgggt
    【解决方案2】:

    我猜你的意思是 RoundedCornerBorder:

    import java.awt.*;
    import java.awt.geom.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.plaf.basic.*;
    
    public class RoundedComboBoxTest {
      public JComponent makeUI() {
        UIManager.put("Panel.background", Color.GRAY);
        UIManager.put("ComboBox.foreground", Color.BLACK);
        UIManager.put("ComboBox.background", Color.GRAY);
        UIManager.put("ComboBox.selectionForeground", Color.WHITE);
        UIManager.put("ComboBox.selectionBackground", Color.GRAY);
        UIManager.put("ComboBox.buttonDarkShadow", Color.BLACK);
        UIManager.put("ComboBox.border", new RoundedCornerBorder());
    
        DefaultComboBoxModel<String> m = new DefaultComboBoxModel<>();
        m.addElement("1234");
        m.addElement("5555555555555555555555");
        m.addElement("6789000000000");
        JComboBox<String> combo = new JComboBox<>(m);
        combo.setUI(new BasicComboBoxUI() {
          @Override protected JButton createArrowButton() {
            JButton b = super.createArrowButton();
            b.setContentAreaFilled(false);
            b.setBackground(Color.GRAY);
            b.setBorder(BorderFactory.createEmptyBorder());
            return b;
          }
        });
        Object o = combo.getAccessibleContext().getAccessibleChild(0);
        ((JComponent)o).setBorder(
            BorderFactory.createMatteBorder(0,1,1,1,Color.BLACK));
        JPanel p = new JPanel(new BorderLayout());
        p.add(combo, BorderLayout.NORTH);
        p.setOpaque(true);
        p.setBackground(Color.GRAY);
        p.setBorder(BorderFactory.createEmptyBorder(15,15,15,15));
        return p;
      }
      public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
          @Override public void run() {
            createAndShowGUI();
          }
        });
      }
      public static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new RoundedComboBoxTest().makeUI());
        f.setSize(320, 240);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
      }
    }
    class RoundedCornerBorder extends AbstractBorder {
      @Override public void paintBorder(
          Component c, Graphics g, int x, int y, int width, int height) {
        Graphics2D g2 = (Graphics2D)g.create();
        g2.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int r = 12;
        Area round = new Area(
            new RoundRectangle2D.Float(x, y, width-1, height-1, r, r));
        Rectangle b = round.getBounds();
        b.setBounds(b.x, b.y + r, b.width, b.height - r);
        round.add(new Area(b));
    
        Container parent = c.getParent();
        if(parent!=null) {
          g2.setColor(parent.getBackground());
          Area corner = new Area(new Rectangle2D.Float(x, y, width, height));
          corner.subtract(round);
          g2.fill(corner);
        }
        g2.setColor(Color.BLACK);
        g2.draw(round);
        g2.dispose();
      }
      @Override public Insets getBorderInsets(Component c) {
        return new Insets(4, 8, 4, 8);
      }
      @Override public Insets getBorderInsets(Component c, Insets insets) {
        insets.left = insets.right = 8;
        insets.top = insets.bottom = 4;
        return insets;
      }
    }
    

    【讨论】:

      【解决方案3】:

      您必须定义自己的自定义渲染器,查看此tutorial 以了解如何定义。

      您也可以在 MyComboBox.java 中设置背景和前景,但这不会影响所选项目的前景、背景。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-27
        • 2013-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-28
        相关资源
        最近更新 更多