2016-07-05 4 views
0

Я пишу GUI с помощью Swing. У меня есть на заказ письмо JComboBox с использованием ListCellRenderer и BasicComboBoxEditor.Изменить цвет выделения (после выбора) в JComboBox

В моем методе getListCellRendererComponent() я изменяю цвет списка в зависимости от того, выбран ли элемент (мышь висит выше), что приятно и все, но я не хочу, чтобы выбор менял цвет фона после выбора, который он делает в настоящее время.

Первое изображение показывает, как выглядит интерфейс перед выбором, а второй показывает, как он выглядит.

Before selection is made After selection is made

ВОПРОС

Как изменить фон "выбор" в "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

Я добавил MCVE и, как вы можете видеть, что это «проблема», что JComboBox сфокусирован, что имеет отношение к моему вопросу. Я добавил кнопку рядом с ComboBox, чтобы помочь удалить фокус из ComboBox.

Просто сделайте setFocusable(false), исправьте его, но также уберите часть функциональности остальной части программы, так что это нежелательно.

ответ

3
  • для лучшей помощи рано опубликовать SSCCE/MCVE, короткие, работоспособный, компилируется с закодированным значением для JComboBox/XxxComboBoxModel в локальных переменной
  • JList имеет логическое массив реализованного по умолчанию в API (никакой идеи, Что скрыта в String trueFalseItem = Boolean.toString(tempValue); и значением, хранящимся JComboBox model)
  • это просто код минимум, чтобы проверить isSelected и изменить JList.setSelectionXxx внутри DefaultListCellRenderer

, например (код в SSCCE/MCVE форме)

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

Не очень это я искал. Я полагаю, что моя проблема связана с тем, что «JComboBox» «сфокусирован», потому что, как только я убеждаюсь, что какой-то другой элемент сфокусирован, «JComboBox» выглядит так, как я хочу. Спасибо, в любом случае. – Zeliax

+0

моя проблема связана с тем, что JComboBox «сфокусирован» == 'isSelected' или' cellHasFocus', оба имеют отношение к 'JList.setSelectionForeground' /' Background', без идеи без вашего кода в форме SSCCE/MCVE – mKorbel

+0

Я добавлю MCVE, когда я получу время, чтобы лучше объяснить мою проблему. И да. Я уверен, что вы правы в части JList. – Zeliax

0

Вот короткий демо 2 JCombos, один из которых не изменит цвет фона при выборе:

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

(Большая заслуга в этом answer)

Смежные вопросы