2016-07-05 15 views
0

Ich schreibe eine GUI mit Swing. Ich habe eine benutzerdefinierte geschrieben JComboBox mit einem ListCellRenderer und einem BasicComboBoxEditor.Ändern Sie die Farbe der Auswahl (nach Auswahl) in einer JComboBox

In meiner getListCellRendererComponent() Methode ändere ich die Farbe der Liste basierend darauf, ob das Element "ausgewählt" ist (die Maus schwebt oben), das ist nett und alle, aber ich möchte nicht die Auswahl Hintergrundfarbe ändern sobald eine Entscheidung getroffen wurde, was sie gerade tut.

Das erste Bild zeigt, wie das Interface aussieht, bevor eine Auswahl getroffen wurde, und das zweite zeigt, wie es aussieht.

Before selection is made After selection is made

FRAGE

Wie ändere ich den Hintergrund der "Auswahl" auf die "stockColor"?

MCVE

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.util.Vector; 

import javax.swing.DefaultComboBoxModel; 
import javax.swing.JButton; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JList; 
import javax.swing.JPanel; 
import javax.swing.ListCellRenderer; 
import javax.swing.plaf.basic.BasicComboBoxEditor; 

public class TFComboBox extends JComboBox{ 

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

    public static void createAndShowGUI(){ 
     JFrame frame = new JFrame("MCVE"); 

     JPanel pane = new JPanel(new BorderLayout()); 
     TFComboBox cb = new TFComboBox(); 
     boolean[] tf = {true, false}; 
     cb.addItems(tf); 

     JButton b = new JButton("Click me!"); 

     pane.add(cb, BorderLayout.CENTER); 
     pane.add(b, BorderLayout.LINE_END); 

     frame.add(pane); 

     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    private DefaultComboBoxModel model; 
    private Vector<Boolean> comboBoxItems; 
    private JComboBox comboBox; 

    public TFComboBox(){ 
     comboBoxItems = new Vector<Boolean>(); 
     comboBoxItems.add(Boolean.TRUE); 
     comboBoxItems.add(Boolean.FALSE); 

     comboBox = new JComboBox(comboBoxItems); 

     model = new DefaultComboBoxModel(); 
     setModel(model); 
     setRenderer(new TrueFalseComboRenderer()); 
     setEditor(new TrueFalseComboEditor()); 
    } 

    public void addItems(boolean[] items){ 
     for(boolean anItem : items){ 
      model.addElement(anItem); 
     } 
    } 
} 

class TrueFalseComboRenderer extends JPanel implements ListCellRenderer { 

    private JLabel labelItem = new JLabel(); 
    private Color stockColor = labelItem.getBackground(); 

    public TrueFalseComboRenderer(){ 
     setLayout(new BorderLayout()); 
     labelItem.setOpaque(true); 
     labelItem.setHorizontalAlignment(JLabel.CENTER); 

     add(labelItem); 

     setBackground(Color.LIGHT_GRAY); 
    } 

    @Override 
    public Component getListCellRendererComponent(JList list, Object value, 
      int index, boolean isSelected, boolean cellHasFocus) { 

     boolean tempValue = (boolean) value;  
     labelItem.setText(Boolean.toString(tempValue)); 

     if(isSelected){ 
      labelItem.setBackground(stockColor.darker()); 
      labelItem.setForeground(Color.WHITE); 
     } else { 
      labelItem.setBackground(stockColor); 
      labelItem.setForeground(Color.BLACK); 
     } 

     return this; 
    } 
} 

class TrueFalseComboEditor extends BasicComboBoxEditor { 

    private JLabel labelItem = new JLabel(); 
    private JPanel panel = new JPanel(); 
    private Object selectedItem; 

    public TrueFalseComboEditor() { 
     labelItem.setOpaque(false); 
     labelItem.setHorizontalAlignment(JLabel.CENTER); 
     labelItem.setForeground(Color.WHITE); 

     panel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 2)); 
     panel.setBackground(Color.BLUE); 
     panel.add(labelItem); 
    } 

    public Component getEditorComponent(){ 
     return this.panel; 
    } 

    public Object getItem(){ 
     return this.selectedItem; 
    } 

    public void setItem(Object item){ 
     if(item == null){ 
      return; 
     } 

     this.selectedItem = item; 
     labelItem.setText(item.toString()); 
    } 
} 

EDIT

Ich habe eine MCVE hinzugefügt und wie man sehen kann es das „Problem“ ist, dass die JComboBox konzentriert sich das mit meiner Frage zu tun hat. Ich habe eine Schaltfläche neben der ComboBox platziert, um den Fokus von der ComboBox zu entfernen.

Einfach tun setFocusable(false) würde es beheben, aber auch etwas von der Funktionalität des Rests des Programms wegnehmen, so dass dies nicht gewünscht ist.

Antwort

3
  • für eine bessere Hilfe früher veröffentlichen ein SSCCE/MCVE, kurz, runnable, übersetzbar mit fest codierten Wert für JComboBox/XxxComboBoxModel in lokalen Variablen
  • JList hat Boolean Array als Standard in API implementiert (keine Ahnung, was String trueFalseItem = Boolean.toString(tempValue); in versteckt und mit dem Wert gespeichert JComboBox model)
  • dies ist nur Code Minimum isSelected zu testen und JList.setSelectionXxx innerhalb DefaultListCellRenderer
zu ändern

beispiel (Code in SSCCE/MCVE Form)

enter image description here

.

enter image description here

.

import java.awt.Color; 
import java.awt.Component; 
import java.awt.event.ActionEvent; 
import java.util.Vector; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.DefaultListCellRenderer; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JList; 
import javax.swing.SwingUtilities; 

public class ComboBoxBooleanModel { 

    private javax.swing.Timer timer = null; 
    private Vector<Boolean> comboBoxItems; 
    private JComboBox box; 

    public ComboBoxBooleanModel() { 
     comboBoxItems = new Vector<Boolean>(); 
     comboBoxItems.add(Boolean.TRUE); 
     comboBoxItems.add(Boolean.FALSE); 
     box = new JComboBox(comboBoxItems); 
     box.setRenderer(new DefaultListCellRenderer() { 
      @Override 
      public Component getListCellRendererComponent(JList list, Object value, 
        int index, boolean isSelected, boolean cellHasFocus) { 
       Component c = super.getListCellRendererComponent(
         list, value, index, isSelected, cellHasFocus); 
       if (c instanceof JLabel) { 
        JLabel l = (JLabel) c; 
        if (Boolean.TRUE.equals(value)) { 
         l.setBackground(Color.RED); 
         if (isSelected) { 
          list.setSelectionForeground(Color.RED); 
          list.setSelectionBackground(Color.BLUE); 
         } 
        } else if (Boolean.FALSE.equals(value)) { 
         l.setBackground(Color.BLUE); 
         if (isSelected) { 
          list.setSelectionForeground(Color.BLUE); 
          list.setSelectionBackground(Color.RED); 
         } 
        } 
        return l; 
       } 
       return c; 
      } 
     }); 
     JFrame frame = new JFrame(""); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(box); 
     frame.setLocationRelativeTo(null); 
     frame.pack(); 
     frame.setVisible(true); 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       box.setSelectedIndex(1); 
      } 
     }); 
     start(); 
    } 

    private void start() { 
     timer = new javax.swing.Timer(2250, updateCol()); 
     timer.start(); 
    } 

    public Action updateCol() { 
     return new AbstractAction("text load action") { 
      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       if (box.getSelectedItem() == (Boolean) false) { 
        box.setSelectedItem((Boolean) true); 
       } else { 
        box.setSelectedItem((Boolean) false); 
       } 
      } 
     }; 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       ComboBoxBooleanModel comboBoxModel = new ComboBoxBooleanModel(); 
      } 
     }); 
    } 
} 
+0

Nicht wirklich das habe ich gesucht. Ich nehme an, dass mein Problem damit zu tun hat, dass die 'JComboBox' 'fokussiert' ist, denn sobald ich sicher bin, dass ein anderes Element fokussiert ist, sieht die' JComboBox' so aus, wie ich es möchte. Danke trotzdem. – Zeliax

+0

mein Problem hat etwas damit zu tun, dass die JComboBox "fokussiert" ist == 'isSelected' oder' cellHasFocus', beide haben mit 'JList.setSelectionForeground' /' Background' zu tun, keine Idee ohne Ihren Code im SSCCE/MCVE-Formular – mKorbel

+0

Ich werde ein MCVE hinzufügen, wenn ich Zeit habe, mein Problem besser zu erklären. Und ja. Ich bin mir ziemlich sicher, dass Sie mit dem JList Teil recht haben. – Zeliax

0

Hier ist eine kurze Demo von 2 JCombos, von denen eine, wenn sie ausgewählt wird nicht die Hintergrundfarbe ändern:

public static void main(String[] args){ 

    JFrame frame = new JFrame("Combos BG Color test"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setLocationRelativeTo(null); 
    frame.getContentPane().setPreferredSize(new Dimension(400, 40)); 

    JPanel mainPanel = new JPanel(); 
    mainPanel.setLayout(new GridLayout(1,2)); 
    frame.add(mainPanel); 

    JComboBox<String> aCombo = new JComboBox<>(new String[]{"A","B","C"}); 
    mainPanel.add(aCombo); 

    JComboBox<String> bCombo = new JComboBox<>(new String[]{"1","2","3"}); 
    Color bgColor = bCombo.getBackground(); 
    bCombo.setRenderer(new DefaultListCellRenderer() { 
     @Override 
     public void paint(Graphics g) { 
      setBackground(bgColor); 
      super.paint(g); 
     } 
    }); 

    mainPanel.add(bCombo); 
    frame.pack(); 
    frame.setVisible(true); 
} 

(Die meisten der Kredit geht an diesem answer)