2017-04-27 151 views
0

我一直試圖找出現在6個小時。我終於得到了顏色根據需要改變,但我只想保持ComboBox的箭頭的默認顏色。JComboBox setBackground()不改變箭頭的顏色

這裏是代碼...

注:編輯的代碼編譯沒有圖片所示的背景...

import org.apache.commons.lang3.ArrayUtils; 

import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 

import javax.imageio.ImageIO; 
import javax.swing.*; 
import javax.swing.border.Border; 
import javax.swing.border.TitledBorder; 
import javax.swing.plaf.ColorUIResource; 
import javax.swing.plaf.metal.MetalComboBoxButton; 

public class TestGui extends JFrame { 
    private final String[] guiCharSelDefault = {"--- Select Character ---"}; 
    private final String[] characters = {"SelectedTextOne", "SelectedTextTwo", "SelectedTextThree", "SelectedTextFour"}; 
    private final String[] guiCharSel = (String[]) ArrayUtils.addAll(guiCharSelDefault, characters); 
    private JComboBox charCombo = createStandardCombo(guiCharSel); 
    private JPanel topFrame = createTopFrame(); 
    private JScrollPane topFrameScroll = createTopScrollPane(); 
    private JPanel centerFrame = createCenterFrame(); 

    //************************************************************************************** 
    // Constructor 

    TestGui(){ 
     add(topFrameScroll, BorderLayout.NORTH); 
     add(centerFrame, BorderLayout.CENTER); 

     setSize(800,600); 
     setVisible(true); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 

    //************************************************************************************** 
    // Support Methods 
    private static GridBagConstraints setGbc(int gridx, int gridy, int gridWidth, int gridHeight, int ipadx, int ipady, String anchorLocation, double weightx, double weighty, Insets insets){ 
     GridBagConstraints gbc = new GridBagConstraints(); 

     if (anchorLocation.toUpperCase().equals("NORTHWEST")){ 
      gbc.anchor = GridBagConstraints.NORTHWEST; 
     } else if (anchorLocation.toUpperCase().equals("NORTH")){ 
      gbc.anchor = GridBagConstraints.NORTH; 
     } else if (anchorLocation.toUpperCase().equals("NORTHEAST")){ 
      gbc.anchor = GridBagConstraints.NORTHEAST; 
     } else if (anchorLocation.toUpperCase().equals("WEST")){ 
      gbc.anchor = GridBagConstraints.WEST; 
     } else if (anchorLocation.toUpperCase().equals("EAST")){ 
      gbc.anchor = GridBagConstraints.EAST; 
     } else if (anchorLocation.toUpperCase().equals("SOUTHWEST")){ 
      gbc.anchor = GridBagConstraints.SOUTHWEST; 
     } else if (anchorLocation.toUpperCase().equals("SOUTH")){ 
      gbc.anchor = GridBagConstraints.SOUTH; 
     } else if (anchorLocation.toUpperCase().equals("SOUTHEAST")){ 
      gbc.anchor = GridBagConstraints.SOUTHEAST; 
     } else { 
      gbc.anchor = GridBagConstraints.CENTER; 
     } 

     gbc.gridx = gridx; // column 
     gbc.gridy = gridy; // row 
     gbc.gridwidth = gridWidth; // number of columns 
     gbc.gridheight = gridHeight; // number of rows 
     gbc.ipadx = ipadx; // width of object 
     gbc.ipady = ipady; // height of object 
     gbc.weightx = weightx; // shifts rows to side of set anchor 
     gbc.weighty = weighty; // shifts columns to side of set anchor 
     gbc.insets = insets; // placement inside cell 
     gbc.fill = GridBagConstraints.HORIZONTAL; 
     gbc.fill = GridBagConstraints.VERTICAL; 

     return gbc; 
    } 

    private Insets setInsets(int top, int left, int bottom, int right){ 
     Insets insets = new Insets(top,left,bottom,right); 
     return insets; 
    } 

    //************************************************************************************** 
    // Interactive Object Methods 

    private JComboBox createStandardCombo(String[] defaultValues){ 
     JComboBox comboBox = new JComboBox(defaultValues); 
     ComboBoxRenderer cbr = new ComboBoxRenderer(); 
     DefaultListCellRenderer dlcr = new DefaultListCellRenderer(); 
     dlcr.setHorizontalTextPosition(SwingConstants.CENTER); 
     comboBox.setRenderer(cbr); 
     comboBox.setPrototypeDisplayValue("X" + guiCharSelDefault + "X"); 
     return comboBox; 
    } 

    //************************************************************************************** 
    // Object Action Methods 

    private void setComboBoxColorBackgroundWithMetalArrow(Color color){ 
     int componentCount = charCombo.getComponentCount(); 
     for (int i = 0; i < componentCount; i++) { 
      Component component = charCombo.getComponent(i); 
      if (component instanceof MetalComboBoxButton) { 
       MetalComboBoxButton metalComboBoxButton = 
         (MetalComboBoxButton) component; 
       Icon comboIcon = metalComboBoxButton.getComboIcon(); 
       BufferedImage bufferedImage = 
         new BufferedImage(
           comboIcon.getIconWidth(), 
           comboIcon.getIconHeight(), 
           BufferedImage.TYPE_INT_ARGB); 
       comboIcon.paintIcon(
         metalComboBoxButton, bufferedImage.getGraphics(), 0, 0); 
      } 
     } 
    } 

    private void setCharComboAction(){ 
     charCombo.addActionListener(
       new ActionListener() { 
        public void actionPerformed(ActionEvent e) { 
         String charName = ((JComboBox)(e.getSource())).getSelectedItem().toString(); 
         if (!(charName.equals(guiCharSelDefault[0]))){ 
          DefaultListCellRenderer dlcr = new DefaultListCellRenderer(); 
          DefaultComboBoxModel model = new DefaultComboBoxModel(characters); 
          model.setSelectedItem(charName); 
          charCombo.setModel(model); 
          if (charName.equals("SelectedTextOne")){ 
           //charCombo.getEditor().getEditorComponent().setBackground(Color.GREEN); 
           charCombo.setBackground(Color.GREEN); 
          } else if (charName.equals("SelectedTextTwo")){ 
           charCombo.setBackground(Color.RED); 
          } else { 
           charCombo.setBackground(dlcr.getBackground()); 
          } 
         } 
        } 
       } 
     ); 
    } 

    //************************************************************************************** 
    // Panel Methods 

    private JPanel createTopFrame(){ 
     JPanel pnl = new JPanel(); 

     pnl.setLayout(new GridBagLayout()); 

     setCharComboAction(); 
     pnl.add(charCombo, setGbc(0,0, 1,1, 0,0, "WEST", 0, 0, setInsets(0, 10, 0, 0))); 
     JButton button = new JButton("Button"); 
     pnl.add(button, setGbc(0,1, 1,1, 0,0, "WEST", 0, 0, setInsets(0, 10, 0, 0))); 

     pnl.setOpaque(false); 
     return pnl; 
    } 

    private JScrollPane createTopScrollPane(){ 
     JScrollPane scrollPane = new JScrollPane(); 
     Border raisedBevel = BorderFactory.createRaisedBevelBorder(); 
     Border lineBorder = BorderFactory.createMatteBorder(2, 2, 2, 2, new Color(224,224,224)); 
     Border loweredBevel = BorderFactory.createLoweredBevelBorder(); 
     Border compoundSetup = BorderFactory.createCompoundBorder(raisedBevel, lineBorder); 
     Border compoundFinal = BorderFactory.createCompoundBorder(compoundSetup, loweredBevel); 

     scrollPane.setBorder(compoundFinal); 
     scrollPane.setOpaque(false); 
     scrollPane.getViewport().setOpaque(false); 
     scrollPane.getViewport().setView(topFrame); 
     return scrollPane; 
    } 

    private JPanel createCenterFrame() { 
     JPanel pnl = new JPanel(); 
     Border raisedBevel = BorderFactory.createRaisedBevelBorder(); 
     Color lineColor = new Color(224, 224, 224); 
     Border lineBorder = BorderFactory.createMatteBorder(5, 5, 5, 5, lineColor); 
     Border loweredBevel = BorderFactory.createLoweredBevelBorder(); 
     Border compoundSetup = BorderFactory.createCompoundBorder(raisedBevel, lineBorder); 
     Border compoundFinal = BorderFactory.createCompoundBorder(compoundSetup, loweredBevel); 
     TitledBorder topFrameTitle = BorderFactory.createTitledBorder(compoundFinal, "Stuff"); 
     topFrameTitle.setTitleJustification(TitledBorder.CENTER); 

     pnl.setBorder(topFrameTitle); 
     pnl.setLayout(new GridBagLayout()); 

     pnl.setOpaque(false); 
     return pnl; 
    } 

    //************************************************************************************** 

    public static void main(String[] args) { 

     new TestGui(); 
    } 
} 

注:我使用的是自定義的渲染器。下面是該代碼...

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

class ComboBoxRenderer extends JLabel implements ListCellRenderer 
{ 
    private Color selectionBackgroundColor; 
    private DefaultListCellRenderer dlcr = new DefaultListCellRenderer(); 

    // Constructor 
    public ComboBoxRenderer() 
    { 
     setOpaque(true); 
     setHorizontalAlignment(CENTER); 
     setVerticalAlignment(CENTER); 
     selectionBackgroundColor = this.dlcr.getBackground(); // Have to set a color, else a compiler error will occur 
    } 

    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) 
    { 
     // Set the list background color to default color (default color will show once selection is made) 
     setBackground(list.getBackground()); 
     Color mouseHoverHighlight = Color.LIGHT_GRAY; 
     setText((String)value); 

     // Check which item is selected 
     if(isSelected) 
     { 
      // Set background color of the item your cursor is hovering over to the original background color 
      setBackground(mouseHoverHighlight); 
     } 
     else 
     { 
      // Set background to specific color depending on text value 
      String selectedTextInDropdownList = getText(); 
      if (selectedTextInDropdownList.equals("SelectedTextOne")) { 
       setBackground(Color.GREEN); 
      } else if (selectedTextInDropdownList.equals("SelectedTextTwo")) { 
       setBackground(Color.RED); 
      } else { 
       setBackground(this.dlcr.getBackground()); 
      } 
     } 
     String selectedText = getText(); 
     if (selectedText.equals("SelectedTextOne")){ 
      list.setSelectionBackground(Color.GREEN); 
     } else if (selectedText.equals("SelectedTextTwo")){ 
      list.setSelectionBackground(Color.RED); 
     } else { 
      list.setSelectionBackground(this.dlcr.getBackground()); 
     } 

     return this; 
    } 
} 

步驟來重現錯誤:

enter image description here

enter image description here

預期結果

enter image description here

+0

你能更好地描述一下你所尋找的行爲是什麼嗎?我知道你不想讓箭頭改變顏色,但你究竟想要做什麼?另外,如果您可以編輯該程序,那麼我們可以更輕鬆地運行該程序。我可以通過刪除一些代碼來運行它,比如對BackgroundPanel的引用,但是如果我們可以將它粘貼到編輯器中,對我們來說很好。 (儘管我在Mac上,但不幸的是,所以我實際上無法幫助解決您遇到的問題.Mac不會爲箭頭着色,因爲它們對LAF有更具體的風格。) – Radiodef

+0

實際上,我想我能用金屬LAF重現它。是否有一個理由,你需要在動作執行方法中調用'charCombo.setBackground(...)'?來自渲染器的顏色應該顯示出來,所以我不認爲你需要在組合框本身上設置背景。在組合框上設置背景似乎是改變了箭頭的顏色。 – Radiodef

+1

*「是否有一個理由,您需要在操作執行方法中調用charCombo.setBackground(...)?」*。是的,原因在這裏列出> http://stackoverflow.com/questions/43646234/custom-jcomboboxrenderer-change-background-color-depending-on-text-selection –

回答

2

你的方法是正確的,但是BasicComboBoxUI在你的車輪上放了一個輻條。幸運的是,我有一個技巧,這有助於避免這個問題。

import java.awt.Color; 
import java.awt.Component; 
import java.awt.Font; 

import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.UIManager; 
import javax.swing.WindowConstants; 
import javax.swing.plaf.basic.BasicComboBoxRenderer; 

@SuppressWarnings("unchecked") 
public class ComboBgTest { 

    private static final String[] VALUES = {"One", "Two", "Three"}; 
    @SuppressWarnings("serial") 
    public static void main(String[] args) { 
     JComboBox<String> cb = new JComboBox<>(VALUES); 
     cb.setSelectedItem(null); 
     cb.setRenderer(new BasicComboBoxRenderer() { 
      boolean ignoreBG = true; 
      @Override 
      public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, 
        boolean cellHasFocus) { 
       ignoreBG = false; 
       Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 
       if (index == -1) { // check whether we are render the item shown at top 
        if (VALUES[0].equals(value)) { 
         c.setBackground(Color.RED); 
        } else if (VALUES[1].equals(value)) { 
         setBackground(Color.GREEN); 
        } else if (VALUES[2].equals(value)) { 
         setBackground(Color.BLUE); 
        } 
       } 
       ignoreBG = true; 
       return this; 
      } 

      @Override 
      public void setBackground(Color bg) { 
       // ignore all BG which is set from outside. 
       if (!ignoreBG) { 
        super.setBackground(bg); 
       } 
      } 
     }); 
     JFrame frm = new JFrame("Combo test"); 
     frm.add(cb); 
     frm.pack(); 
     frm.setLocationRelativeTo(null); 
     frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     frm.setVisible(true); 
    } 
} 

P.S.同樣的方法也適用於字體和foregorund。

+0

不得不改變線'JComboBox cb = new JComboBox <>(VALUES);'到'JComboBox cb = new JComboBox(VALUES);'。除此之外,它似乎工作。稍後當我完成當前使用相同邏輯的任務時,我將對其進行剖析。謝謝:) –

+0

@FiddleFreak可能你使用了一個非常古老的java版本。這個代碼是用Java 7編譯和測試的。 –

+0

剛剛發佈的Opps,我們使用的是相同的基本解決方案:P – MadProgrammer

1

[言論]你真的要學會轉降低您的示例代碼的最低要求說明問題,它需要很多的努力來重構每次代碼:P [/咆哮]

什麼發生的是,JComboBox正在改變選定項目從列表中選擇(和呈現)後的背景顏色。一個可能的解決方案是簡單地通過具有總是返回,不管什麼設置的,例如「覆蓋」顏色繞過這個...

Background ChangedBackground Changed

import java.awt.Color; 
import java.awt.Component; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.HeadlessException; 
import javax.swing.DefaultListCellRenderer; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JList; 
import javax.swing.JTextField; 
import javax.swing.SwingUtilities; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class TestGui extends JFrame { 

    private final String[] guiCharSel = {"--- Select Character ---", "SelectedTextOne", "SelectedTextTwo", "SelectedTextThree", "SelectedTextFour"}; 

    public static void main(String[] args) { 
     new TestGui(); 
    } 

    public TestGui() throws HeadlessException { 
     try { 
      UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); 
     } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
      ex.printStackTrace(); 
     } 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JComboBox box = new JComboBox(guiCharSel); 
       box.setRenderer(new ComboBoxRenderer()); 

       JTextField field = new JTextField(10); 

       JFrame frame = new JFrame(); 
       frame.setLayout(new GridBagLayout()); 
       GridBagConstraints gbc = new GridBagConstraints(); 
       gbc.gridwidth = GridBagConstraints.REMAINDER; 
       frame.add(box, gbc); 
       frame.add(field, gbc); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    class ComboBoxRenderer extends DefaultListCellRenderer { 

     private Color overrideBackground; 
     private Color mouseHoverHighlight = Color.LIGHT_GRAY; 

     // Constructor 
     public ComboBoxRenderer() { 
      setOpaque(true); 
      setHorizontalAlignment(CENTER); 
      setVerticalAlignment(CENTER); 
     } 

     @Override 
     public void setOpaque(boolean isOpaque) { 
      System.out.println("setOpaque " + isOpaque); 
      //NOOP 
     } 

     @Override 
     public boolean isOpaque() { 
      return true; 
     } 

     @Override 
     public void setBackground(Color bg) { 
      System.out.println(">> Background = " + bg); 
      super.setBackground(bg); //To change body of generated methods, choose Tools | Templates. 
     } 

     @Override 
     public Color getBackground() { 
      return overrideBackground == null ? super.getBackground() : overrideBackground; 
     } 

     public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 
      // Set the list background color to default color (default color will show once selection is made) 
      overrideBackground = null; 
      setText((String) value); 

      // Check which item is selected 
      System.out.println(value + "; isSelected = " + isSelected + "; cellHasFocus = " + cellHasFocus); 
      if (isSelected) { 
       // Set background color of the item your cursor is hovering over to the original background color 
       setBackground(mouseHoverHighlight); 
      } else { 
       // Set background to specific color depending on text value 
       String selectedTextInDropdownList = getText(); 
       if (selectedTextInDropdownList.equals("SelectedTextOne")) { 
        System.out.println(">> Green"); 
        overrideBackground = Color.GREEN; 
       } else if (selectedTextInDropdownList.equals("SelectedTextTwo")) { 
        System.out.println(">> Red"); 
        overrideBackground = Color.RED; 
       } else { 
        overrideBackground = null; 
       } 
      } 

      return this; 
     } 
    } 
} 

這僅會在後由於該項目已呈現爲「已選中」,因此組合框將失去焦點。你可以改變選擇背景,但我找不到任何像樣的狀態組合,它很容易做