LookAndFeel blocking JComboBox background change? - java

The goal is to change the background of all combo box when LookAndFeel is in the main method.
But I get different results when LookAndFeel exists and not.
Without LookAndFeel: JComboBox is visible after JFrame resizing
import javax.swing.*;
import java.awt.*;
import static java.awt.Color.WHITE;
public class TestFrame extends JFrame {
private static final String[] ANIMALS = new String[]{"Cat", "Mouse", "Dog", "Elephant", "Bird", "Goat", "Bear"};
public TestFrame() {
setSize(600, 300);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JComboBox<String> comboBox = new JComboBox<>();
comboBox.setModel(new DefaultComboBoxModel<>(ANIMALS));
comboBox.setForeground(WHITE);
comboBox.setBackground(new Color(71, 81, 93));
comboBox.getEditor().getEditorComponent().setBackground(new Color(71, 81, 93));
comboBox.getEditor().getEditorComponent().setForeground(WHITE);
comboBox.setRenderer(new DefaultListCellRenderer() {
#Override
public void paint(Graphics g) {
setBackground(new Color(71, 81, 93));
setForeground(WHITE);
super.paint(g);
}
});
panel.add(comboBox);
add(panel);
}
public static void main(String[] args) {
new TestFrame();
}
}
With LookAndFeel:
import javax.swing.*;
import java.awt.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.awt.Color.WHITE;
public class TestFrame extends JFrame {
private static final String[] ANIMALS = new String[]{"Cat", "Mouse", "Dog", "Elephant", "Bird", "Goat", "Bear"};
public TestFrame() {
setSize(600, 300);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JComboBox<String> comboBox = new JComboBox<>();
comboBox.setModel(new DefaultComboBoxModel<>(ANIMALS));
comboBox.setForeground(WHITE);
comboBox.setBackground(new Color(71, 81, 93));
comboBox.getEditor().getEditorComponent().setBackground(new Color(71, 81, 93));
comboBox.getEditor().getEditorComponent().setForeground(WHITE);
comboBox.setRenderer(new DefaultListCellRenderer() {
#Override
public void paint(Graphics g) {
setBackground(new Color(71, 81, 93));
setForeground(WHITE);
super.paint(g);
}
});
panel.add(comboBox);
add(panel);
}
public static void main(String[] args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(TestFrame.class.getName()).log(Level.SEVERE, null, ex);
}
/* Create and display the form */
EventQueue.invokeLater(new Runnable() {
public void run() {
new TestFrame();
}
});
}
}
How can I achieve full painting of the combo box with LookAndFeel enabled?

There is no thing like a disabled or enabled LookAndFeel. You always have a Look and feel set in your aplication. You just seem to set another LookAndFeel, which in your case is Nimbus. However, to answer your question, Nimbus sets the DefaultListCellRenderer's opacity-Property to false, (MetalLookAndFeel for example sets it to true) which is the reason for the visual representation you are showing. You should be able to fix this by overriding the getListCellRendererComponent method of DefaultListCellRenderer like so:
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
JComponent comp = (JComponent) super.getListCellRendererComponent(list,
value, index, isSelected, cellHasFocus);
list.setBackground(COMBO_COLOR);
list.setForeground(Color.WHITE);
list.setOpaque(false);
return comp;
}
You also have to set the UIManagers property ComboBox.forceOpaque to false, like so:
UIManager.put("ComboBox.forceOpaque", false);
A full list of the Nimubs defauts can be found here.
A full working example of the fixed problem if needed:
import java.awt.*;
import java.util.Arrays;
import javax.swing.*;
public class JComboBoxExample {
private static final Color COMBO_COLOR = new Color(71, 81, 93);
private static final String[] COMBO_DATA = {"Get back!", "Go!", "Help!", "Careful!"};
public static void main(String[] args) throws Exception {
String nimbus = Arrays.asList(UIManager.getInstalledLookAndFeels())
.stream()
.filter(i -> i.getName().equals("Nimbus"))
.findFirst()
.get()
.getClassName();
UIManager.setLookAndFeel(nimbus);
UIManager.put("ComboBox.forceOpaque", false);
JFrame jf = new JFrame();
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocationRelativeTo(null);
MyComboBox comboBox = new MyComboBox(new DefaultComboBoxModel(COMBO_DATA));
jf.add(comboBox);
jf.pack();
}
private static class MyComboBox extends JComboBox {
public MyComboBox(DefaultComboBoxModel model) {
super(model);
setForeground(Color.WHITE);
setFont(new Font("Arial", Font.PLAIN, 30));
setPreferredSize(new Dimension(350, 50));
setRenderer(new MyRenderer());
}
}
private static class MyRenderer extends DefaultListCellRenderer {
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
JComponent comp = (JComponent) super.getListCellRendererComponent(list,
value, index, isSelected, cellHasFocus);
list.setBackground(COMBO_COLOR);
list.setForeground(Color.WHITE);
list.setOpaque(false);
return comp;
}
}
}
results in:
By the way, I figured this out by using the visual debugger of the NetBeans IDE.

Related

JComboBox custom renderer generics

I have written a renderer for JComboBoxes to replace the milky colour when in
disabled state by a more legible one.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
public class RendererDemo extends JFrame {
public static final long serialVersionUID = 100L;
String[] items= {"one", "two", "three"};
public RendererDemo() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 100);
JComboBox<Object> cmb = new JComboBox<>(items);
// JComboBox<String> cmb = new JComboBox<>(items);
cmb.setRenderer(new DisabledDarkTextRenderer(cmb));
add(cmb, BorderLayout.NORTH);
JCheckBox check = new JCheckBox("Combo enabled", true);
add(check, BorderLayout.SOUTH);
check.addActionListener(e -> cmb.setEnabled(check.isSelected()));
setVisible(true);
}
static public void main(String args[]) {
EventQueue.invokeLater(RendererDemo::new);
}
class DisabledDarkTextRenderer extends DefaultListCellRenderer {
public static final long serialVersionUID = 50378L;
JComboBox<Object> cmb;
ListCellRenderer<Object> origRenderer;
Object defaultResource= UIManager.get("ComboBox.disabledForeground");
public DisabledDarkTextRenderer(JComboBox<Object> cmb) {
this.cmb= cmb;
origRenderer= cmb.getRenderer();
}
public Component getListCellRendererComponent(JList<?> list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Component orig= origRenderer.getListCellRendererComponent(list, value,
index, isSelected, cellHasFocus);
if (cmb.isEnabled())
UIManager.put("ComboBox.disabledForeground", defaultResource);
else
UIManager.put("ComboBox.disabledForeground", new ColorUIResource
(Color.GRAY));
return orig;
}
}
}
However, when I declare the JComboBox as being of type <String>, the code fails to compile due to "incompatible types: ListCellRenderer<CAP#1> cannot be converted to ListCellRenderer<Object> ..."
So I tried to make the renderer more general. From all my attempts to modify the
generic type, the following version is the one with only one error left. It's again the above mentioned error, only that it reads now: "incompatible types: JList<CAP#1> cannot be converted to JList<? extends CAP#2> ...".
How to fix this?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.*;
public class RendererDemo2 extends JFrame {
public static final long serialVersionUID = 100L;
String[] items= {"one", "two", "three"};
public RendererDemo2() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 100);
JComboBox<String> cmb = new JComboBox<>(items);
cmb.setRenderer(new DisabledDarkTextRenderer2(cmb));
add(cmb, BorderLayout.NORTH);
JCheckBox check = new JCheckBox("Combo enabled", true);
add(check, BorderLayout.SOUTH);
check.addActionListener(e -> cmb.setEnabled(check.isSelected()));
setVisible(true);
}
static public void main(String args[]) {
EventQueue.invokeLater(RendererDemo2::new);
}
class DisabledDarkTextRenderer2 extends DefaultListCellRenderer {
public static final long serialVersionUID = 50379L;
JComboBox<?> cmb;
ListCellRenderer<?> origRenderer;
Object defaultResource= UIManager.get("ComboBox.disabledForeground");
public DisabledDarkTextRenderer2(JComboBox<?> cmb) {
this.cmb= cmb;
origRenderer= cmb.getRenderer();
}
public Component getListCellRendererComponent(JList<?> list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Component orig= origRenderer.getListCellRendererComponent(list, value,
index, isSelected, cellHasFocus);
if (cmb.isEnabled())
UIManager.put("ComboBox.disabledForeground", defaultResource);
else
UIManager.put("ComboBox.disabledForeground", new ColorUIResource
(Color.GRAY));
return orig;
}
}
}
Following MadProgrammer's advice my renderer now looks like this:
class DisabledDarkTextRenderer2<T> extends DefaultListCellRenderer {
public static final long serialVersionUID = 50379L;
JComboBox<T> cmb;
ListCellRenderer<?> origRenderer;
Object defaultResource= UIManager.get("ComboBox.disabledForeground");
public DisabledDarkTextRenderer2(JComboBox<T> cmb) {
this.cmb= cmb;
origRenderer= cmb.getRenderer();
}
public Component getListCellRendererComponent(JList<?> list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Component orig= origRenderer.getListCellRendererComponent(list, value,
index, isSelected, cellHasFocus);
if (cmb.isEnabled())
UIManager.put("ComboBox.disabledForeground", defaultResource);
else
UIManager.put("ComboBox.disabledForeground", new ColorUIResource
(Color.GRAY));
return orig;
}
}
but the compile time error persists.
I am using this renderer for combos which change their state at runtime. So I am free from caring in each program to set the colour when needed, as the renderer is doing this automatically for me.
You need to "genericfy" your DisabledDarkTextRenderer2, as an example...
class DisabledDarkTextRenderer2<T> implements ListCellRenderer<T> {
public static final long serialVersionUID = 50379L;
private JComboBox<T> combobox;
private ListCellRenderer<? super T> origRenderer;
public DisabledDarkTextRenderer2(JComboBox<T> combobox) {
this.combobox = combobox;
this.origRenderer = combobox.getRenderer();
}
public static <T> void install(JComboBox<T> combobox) {
combobox.setRenderer(new DisabledDarkTextRenderer2<T>(combobox));
}
#Override
public Component getListCellRendererComponent(JList<? extends T> list, T value, int index, boolean isSelected, boolean cellHasFocus) {
Component orig = origRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (combobox.isEnabled()) {
orig.setForeground(null);
} else {
orig.setForeground(Color.GRAY);
}
return orig;
}
}
Now, having said that, I would discourage you from using UIManager within the renderer, as this will effect ALL components rendered after the change, which may or may not be your desired goal, if so, then just set the value at the start of the application.
The following example will make the default disabled foreground color RED for all comboboxes without you having to do anything else at all.
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ColorUIResource;
public final class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
UIManager.put("ComboBox.disabledForeground", new ColorUIResource(Color.RED));
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(32, 32, 32, 32));
JComboBox<String> cmb = new JComboBox<>(new String[]{"Hello", "Goodbye"});
cmb.setSelectedIndex(0);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(cmb, gbc);
JButton toggle = new JButton("Toggle");
toggle.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cmb.setEnabled(!cmb.isEnabled());
}
});
add(toggle, gbc);
}
}
}

How to change font of JComboBox

I want to change the font size of my JComboBox.
However only not selected item are change, like that :
https://imgur.com/a/WnnyPA6
So I want that selected item are also bold.
I done a custom combobox classe like that :
public class CustomComboBox extends JLabel implements ListCellRenderer {
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
JLabel label = new JLabel(){
public Dimension getPreferredSize(){
return new Dimension(200, 80);
}
};
label.setText(String.valueOf(value));
label.setFont(new Font("Serif", Font.BOLD, 30));
return label;
}
}
You can simply set font for combo box. Something like this:
import java.awt.Dimension;
import java.awt.Font;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
/**
* <code>ComboTest</code>.
*/
public class ComboTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new ComboTest()::startUp);
}
private void startUp() {
JComboBox<String> combo = new JComboBox<>(new String[] {"A", "B", "C"});
combo.setFont(new Font("Serif", Font.BOLD, 30));
combo.setRenderer(new ComboRenderer());
JFrame frm = new JFrame("Combo test");
frm.add(combo);
frm.pack();
frm.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frm.setLocationRelativeTo(null);
frm.setVisible(true);
}
private static class ComboRenderer extends BasicComboBoxRenderer {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 80);
}
}
}
When my suggstion is not helpful in your case please create a small runnable example, so we can also start and debug it.
You can set font for Combo box by using
combo.setFont(new FontUIResource("Roboto",Font.PLAIN,12);

How to programmatically access the display field of a JComboBox? [duplicate]

I am programming an editable combobox in a JFrame Form, but i want to change te background color.
How the program works:
If i click the button "press", then the combobox his background needs to become black.
I tried:
1.
cbo.setBackground(Color.BLACK);
But it did nothing
2
cbo.getEditor().getEditorComponent().setBackground(Color.BLACK);
((JTextField) cbo.getEditor().getEditorComponent()).setOpaque(true);
Does this:
Code example:
public class NewJFrame extends javax.swing.JFrame {
private JComboBox cboCategorie;
public NewJFrame() {
initComponents();
cboCategorie = new JComboBox();
cboCategorie.setBounds(10, 10, 250, 26);
cboCategorie.setVisible(true);
cboCategorie.setEditable(true);
this.add(cboCategorie);
}
private void pressActionPerformed(java.awt.event.ActionEvent evt) {
cboCategorie.getEditor().getEditorComponent().setBackground(Color.BLACK);
((JTextField) cboCategorie.getEditor().getEditorComponent()).setOpaque(true);
}
I am working with the Java JDK7
Any sugestions?
see my code example
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++) {// hack valid only for Metal L&F
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();
}
});
}
}
Turned out to be easy. Create a renderer and set the background color. Then override the renderer's setOpaque method to always set the opacity to true.
class PDFChooser extends JComboBox<String> {
PDFChooser() {
setRenderer(new Renderer());
}
class Renderer extends DefaultListCellRenderer {
#Override
public void setOpaque(boolean makeBackGroundVisible) {
super.setOpaque(true); // THIS DOES THE TRICK
}
#Override
public Component getListCellRendererComponent(JList<?> list,
Object value, int index,
boolean isSelected, boolean cellHasFocus) {
setText((String)value);
setBackground(Color.cyan);
return this;
}
}
}
If you want the popup menu to use the LAF background, you can add a PopupMenuListener to note when the popup is popped. At that time, the setOpaque method would set the opacity false.
It works for me to change the color of a selected item in JComboBox.
JComboBox cmb = new JComboBox();
cmb.setEditable(true);
cmb.setEditor(new WComboBoxEditor(getContentPane().getBackground()));
// To change the arrow button's background
cmb.setUI(new BasicComboBoxUI(){
protected JButton createArrowButton()
{
BasicArrowButton arrowButton = new BasicArrowButton(BasicArrowButton.SOUTH, null, null, Color.GRAY, null);
return arrowButton;
}
});
cmb.setModel(new DefaultComboBoxModel(new String[] { "a", "b", "c" }));
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionListener;
import javax.swing.ComboBoxEditor;
import javax.swing.JTextField;
public class WComboBoxEditor implements ComboBoxEditor
{
JTextField tf;
public WComboBoxEditor(Color background)
{
tf = new JTextField();
tf.setBackground(background);
tf.setBorder(null);
}
public Component getEditorComponent()
{
return tf;
}
public void setItem(Object anObject)
{
if (anObject != null)
{
tf.setText(anObject.toString());
}
}
public Object getItem()
{
return tf.getText();
}
public void selectAll()
{
tf.selectAll();
}
public void addActionListener(ActionListener l)
{
tf.addActionListener(l);
}
public void removeActionListener(ActionListener l)
{
tf.removeActionListener(l);
}
}
If you'd like to change the color of items in JCombobox except for a selected one, customize ListCellRenderer.

Change color of selection (after selection) in a JComboBox

I'm writing a GUI using Swing. I have a custom written JComboBox using a ListCellRenderer and a BasicComboBoxEditor.
In my getListCellRendererComponent() method I change the color of the the list based on whether the item is "selected" (mouse is hovering above), which is nice and all, but I don't want the selection to change background color once a choice is made, which it currently does.
The first picture shows how the interface looks before a selection is made, and the second one shows how it looks after.
QUESTION
How do I change the background of the "selection" to the "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
I've added a MCVE and as you can see it is the "problem" that the JComboBox is focused that has to do with my issue. I've placed a button next to the ComboBox to help with removing the focus from the ComboBox.
Simply doing a setFocusable(false) would fix it, but also take away some of the functionality of the rest of the program, so this is not desired.
for better help sooner post an SSCCE / MCVE, short, runnable, compilable, with hardcoded value for JComboBox / XxxComboBoxModel in local variable
JList has Boolean array implemented as default in API (no idea whats hidden in
String trueFalseItem = Boolean.toString(tempValue); and with value stored JComboBox model)
this is just code minimum to test isSelected and to change JList.setSelectionXxx inside DefaultListCellRenderer
for example (code in SSCCE / MCVE form)
.
.
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();
}
});
}
}
Here is a short demo of 2 JCombos, one of which will not change its background color when selected :
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);
}
(Most of the credit goes to this answer)

Making JComboBox transparent

I have a problem with making JComboBox transparent. I tried setting opaque to false and alpha of background 0 but it doesnt work. I guess that i need to change some class that does rendering or something similar.And here is the code..
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JComboBox;
import javax.swing.JTextField;
import javax.swing.plaf.basic.BasicComboBoxUI;
import java.awt.Color;
public class App {
private JFrame frame;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
App window = new App();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public App() {
initialize();
}
private void initialize() {
frame = new JFrame();
frame.getContentPane().setBackground(Color.GREEN);
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" };
JComboBox comboBox = new JComboBox(petStrings);
comboBox.setBounds(149, 99, 155, 20);
comboBox.setOpaque(false);
//comboBox.setBackground(new Color(0,0,0,0));
((JTextField)comboBox.getEditor().getEditorComponent()).setOpaque(false);
comboBox.setUI(new BasicComboBoxUI(){
public void paintCurrentValueBackground(Graphics g,Rectangle bounds,boolean hasFocus){}});
frame.getContentPane().add(comboBox);
}
}
Assuming you just want the ComboBox's text field transparent (not the popup as well), using the following code should work. You need to mess with the ComboBox renderer instead of the editor. The editor is used for if you can type into the ComboBox; The renderer is used if the ComboBox is a list of values only.
comboBox.setOpaque(false);
comboBox.setRenderer(new DefaultListCellRenderer(){
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
JComponent result = (JComponent)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
result.setOpaque(false);
return result;
}});
JComboBox myComboBox = new JComboBox(array);
myComboBox .setOpaque(false);
myComboBox .setEditable(true);
JTextField boxField = (JTextField)myComboBox .getEditor().getEditorComponent();
boxField.setBorder(BorderFactory.createEmptyBorder());
boxField.setBackground(new Color(0, 0, 0, 0));
boxField.setFocusable(false);
The answer is in http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6687960
You need to preset this few things
jcombo.setOpaque(false);
jcombo.setContentAreaFilled(false);
jcombo.setBorderPainted(false);
try this.
yourComboBox.setOpaque(false);
((JTextField)yourComboBox.getEditor().getEditorComponent()).setOpaque(false);
setUI(new BasicComboBoxUI() {
#Override
public void paintCurrentValueBackground(
Graphics g, Rectangle bounds, boolean hasFocus) {
}
});

Categories