2013-03-25 127 views
2

我正在使用Metal L & F.我想制作一个JComboBox,它只有1个像素边框。这不是问题,只要cb是即可编辑。这对应于名为“可编辑”的图片中的第一个cb。不可编辑JComboBox边框

cb.setEditable(true); 
((JTextComponent) (cb.getEditor().getEditorComponent())).setBorder(BorderFactory.createMatteBorder(1, 1, 1, 0, COLOR)); 

但是当我做cb.setEditable(假),额外的边界框内出现(换成红色的图片“下拉”,你看到原来的颜色在图片命名为“固定” )。尽管我试图设置边框,并且我也尝试使用自己的CellRenderer,但边框仍然被绘制。在我看来,不需要的边界不是来自CellRenderer。当我尝试从cb本身操作边框(请参阅注释//)时,它只会添加/删除额外的外边框。 editorComponent似乎也不对我负责。

cb.setRenderer(new CbCellRenderer()); 
//cb.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, COLOR)); 
//cb.setBorder(BorderFactory.createEmptyBorder()); 

class CbCellRenderer implements ListCellRenderer { 

    protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer(); 

    @Override 
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 
     JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
     renderer.setBorder(BorderFactory.createEmptyBorder()); 
     return renderer; 
    }   
} 

我也尝试了一些UI变量,如下面的那些,而不影响这个边界。

UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); 
UIManager.put("ComboBox.selectionForeground", Color.green); 
UIManager.put("ComboBox.disabledBackground", Color.green); 
... 

图片:http://upload.mtmayr.com/dropdown_frame.png(链接断开)

测试完整代码:

import java.awt.*; 
import java.util.Vector; 
import javax.swing.*; 
import javax.swing.plaf.basic.BasicComboPopup; 

public class ComboTest { 

    private Vector<String> listSomeString = new Vector<String>(); 
    private JComboBox editableComboBox = new JComboBox(listSomeString); 
    private JComboBox nonEditableComboBox = new JComboBox(listSomeString); 
    private JFrame frame; 
    public final static Color COLOR_BORDER = new Color(122, 138, 153); 

    public ComboTest() { 
     listSomeString.add("row 1"); 
     listSomeString.add("row 2"); 
     listSomeString.add("row 3"); 
     listSomeString.add("row 4"); 

     editableComboBox.setEditable(true); 
     editableComboBox.setBackground(Color.white); 
     Object child = editableComboBox.getAccessibleContext().getAccessibleChild(0); 
     BasicComboPopup popup = (BasicComboPopup) child; 
     JList list = popup.getList(); 
     list.setBackground(Color.white); 
     list.setSelectionBackground(Color.red); 
     JTextField tf = ((JTextField) editableComboBox.getEditor().getEditorComponent()); 
     tf.setBorder(BorderFactory.createMatteBorder(1, 1, 1, 0, COLOR_BORDER)); 

     nonEditableComboBox.setEditable(false); 
     nonEditableComboBox.setBorder(BorderFactory.createEmptyBorder()); 
     nonEditableComboBox.setBackground(Color.white); 
     Object childNonEditable = nonEditableComboBox.getAccessibleContext().getAccessibleChild(0); 
     BasicComboPopup popupNonEditable = (BasicComboPopup) childNonEditable; 
     JList listNonEditable = popupNonEditable.getList(); 
     listNonEditable.setBackground(Color.white); 
     listNonEditable.setSelectionBackground(Color.red); 

     frame = new JFrame(); 
     frame.setLayout(new GridLayout(0, 1, 10, 10)); 
     frame.add(editableComboBox); 
     frame.add(nonEditableComboBox); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocation(100, 100); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 

     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       ComboTest ct = new ComboTest(); 
      } 
     }); 
    } 
} 
+0

类似过帐: [LINK1](http://stackoverflow.com/questions/10569759/ border-editor-when-rendering-item-in-jcombobox-and-editable-false) [link2](http://stackoverflow.com/questions/10169022/jcombobox-does-not-behave-same-as-jtextfield我怎么可以有它看起来相似) [link3](http://stackoverflow.com/questions/9322903/how-do-you-change-border-of-the-pop-up-section-of-a-jcombobox) [link4](http: //www.stackoverflow.com/questions/776893/remove-border-from-jcombobox) – mtmayr 2013-03-25 17:54:34

回答

2
  • 如何覆盖MetalComboBoxUI#paintCurrentValueBackground(...)
    • 使用JDK 1.7.0_17,视窗7

enter image description here

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.text.*; 
import javax.swing.plaf.*; 
import javax.swing.plaf.basic.*; 
import javax.swing.plaf.metal.*; 

public class ComboBoxUIDemo { 
    private static Color BORDER = Color.GRAY; 
    public JComponent makeUI() { 
    //UIManager.put("ComboBox.foreground", Color.WHITE); 
    //UIManager.put("ComboBox.background", Color.BLACK); 
    //UIManager.put("ComboBox.selectionForeground", Color.CYAN); 
    //UIManager.put("ComboBox.selectionBackground", Color.BLACK); 

    //UIManager.put("ComboBox.buttonDarkShadow", Color.WHITE); 
    //UIManager.put("ComboBox.buttonBackground", Color.GRAY); 
    //UIManager.put("ComboBox.buttonHighlight", Color.WHITE); 
    //UIManager.put("ComboBox.buttonShadow", Color.WHITE); 
    //UIManager.put("ComboBox.editorBorder", BorderFactory.createLineBorder(Color.RED)); 

    Box box = Box.createVerticalBox(); 

    UIManager.put("ComboBox.border", BorderFactory.createEmptyBorder()); 
    for(int i=0; i<2; i++) { // Defalut 
     JComboBox<String> cb = new JComboBox<>(makeModel()); 
     if(i%2==0) setEditable(cb); 
     setPopupBorder(cb); 
     box.add(cb); 
     box.add(Box.createVerticalStrut(10)); 
    } 

    { 
     // Override MetalComboBoxUI#paintCurrentValueBackground(...) 
     JComboBox<String> cb = new JComboBox<>(makeModel()); 
     cb.setUI(new MetalComboBoxUI() { 
     @Override public void paintCurrentValueBackground(
     Graphics g, Rectangle bounds, boolean hasFocus) { 
      //if (MetalLookAndFeel.usingOcean()) { 
      if(MetalLookAndFeel.getCurrentTheme() instanceof OceanTheme) { 
      g.setColor(MetalLookAndFeel.getControlDarkShadow()); 
      g.drawRect(bounds.x, bounds.y, bounds.width, bounds.height - 1); 
      //COMMENTOUT>>> 
      //g.setColor(MetalLookAndFeel.getControlShadow()); 
      //g.drawRect(bounds.x + 1, bounds.y + 1, bounds.width - 2, 
      //   bounds.height - 3); 
      //<<<COMMENTOUT 
      if (hasFocus && !isPopupVisible(comboBox) && arrowButton != null) { 
       g.setColor(listBox.getSelectionBackground()); 
       Insets buttonInsets = arrowButton.getInsets(); 
       if (buttonInsets.top > 2) { 
       g.fillRect(bounds.x + 2, bounds.y + 2, bounds.width - 3, 
          buttonInsets.top - 2); 
       } 
       if (buttonInsets.bottom > 2) { 
       g.fillRect(bounds.x + 2, bounds.y + bounds.height - 
          buttonInsets.bottom, bounds.width - 3, 
          buttonInsets.bottom - 2); 
       } 
      } 
      } else if (g == null || bounds == null) { 
      throw new NullPointerException(
       "Must supply a non-null Graphics and Rectangle"); 
      } 
     } 
     }); 
     setPopupBorder(cb); 

     box.add(cb); 
     box.add(Box.createVerticalStrut(10)); 
    } 

    UIManager.put("ComboBox.border", BorderFactory.createLineBorder(BORDER)); 
    for(int i=0; i<2; i++) { // BasicComboBoxUI 
     JComboBox<String> cb = new JComboBox<>(makeModel()); 
     if(i%2==0) setEditable(cb); 
     cb.setUI(new BasicComboBoxUI()); 
     setPopupBorder(cb); 
     box.add(cb); 
     box.add(Box.createVerticalStrut(10)); 
    } 

    JPanel p = new JPanel(new BorderLayout()); 
    p.setBorder(BorderFactory.createEmptyBorder(10,20,10,20)); 
    p.add(box, BorderLayout.NORTH); 
    return p; 
    } 
    private static void setEditable(JComboBox cb) { 
    cb.setEditable(true); 
    ComboBoxEditor editor = cb.getEditor(); 
    Component c = editor.getEditorComponent(); 
    if(c instanceof JTextField) { 
     JTextField tf = (JTextField)c; 
     tf.setBorder(BorderFactory.createMatteBorder(1,1,1,0,BORDER)); 
    } 
    } 
    private static void setPopupBorder(JComboBox cb) { 
    Object o = cb.getAccessibleContext().getAccessibleChild(0); 
    JComponent c = (JComponent)o; 
    c.setBorder(BorderFactory.createMatteBorder(0,1,1,1,BORDER)); 
    } 
    private static DefaultComboBoxModel<String> makeModel() { 
    DefaultComboBoxModel<String> m = new DefaultComboBoxModel<>(); 
    m.addElement("1234"); 
    m.addElement("5555555555555555555555"); 
    m.addElement("6789000000000"); 
    return m; 
    } 
    public static void main(String[] args) { 
//  OceanTheme theme = new OceanTheme() { 
//  @Override protected ColorUIResource getSecondary2() { 
//   return new ColorUIResource(Color.RED); 
//  } 
//  }; 
//  MetalLookAndFeel.setCurrentTheme(theme); 

    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 ComboBoxUIDemo().makeUI()); 
    f.setSize(320, 240); 
    f.setLocationRelativeTo(null); 
    f.setVisible(true); 
    } 
} 
+0

+1 ....疯狂的黑客,输出看起来像ATARI :-), – mKorbel 2013-03-26 10:23:54

+0

谢谢你aterai!这似乎解决了我的问题!我仍然忙于将它应用到我的程序中。 – mtmayr 2013-03-26 11:58:57

2
  • 不能......,每一个都有得到了相同的边界,必须有另一个边界问题,第一和第二。可编辑JComboBoxes

  • 为更好地帮助越早张贴SSCCE,短,可运行,编译,只是约两JComboBoxes,本机OS,在JDK编译,在JRE拼命地跑

WinXP中的Java6

enter image description here

Win7的Java7

> will be edited

的Win7的Java6

> will be edited

的Win8的Java6

enter image description here

Win8的Java7

> will be edited

从代码

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

感谢您的回答。我已经看到你在另一个线程中发布。我认为你的组合框还会显示我正在谈论的内部边框! – mtmayr 2013-03-25 14:53:17