I am using Metal L&F. I want to make a JComboBox, that has only 1 pixel border. This not a problem, as long as the cb is editable. This corresponds to the first cb in the picture named "Editable".
cb.setEditable(true);
((JTextComponent) (cb.getEditor().getEditorComponent())).setBorder(BorderFactory.createMatteBorder(1, 1, 1, 0, COLOR));
But when I do cb.setEditable(false), an additional border occurs inside the box (changed to red in the picture "Dropdown", you see the original color in the picture named "Fixed"). Although I tried to set the border and I also tried to use my own CellRenderer, the border still gets painted. It seems to me, that the unwanted border does not come from the CellRenderer. When I try to manipulate the border from the cb itself (see comment //), it only adds/removes an additional outer border. The editorComponent also seems not to be responsible to me.
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;
}
}
I also tried out some UI variables like the ones below without taking affect on this border.
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
UIManager.put("ComboBox.selectionForeground", Color.green);
UIManager.put("ComboBox.disabledBackground", Color.green);
...
Image: http://upload.mtmayr.com/dropdown_frame.png (link broken)
Complete code for testing:
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();
}
});
}
}
How about override MetalComboBoxUI#paintCurrentValueBackground(...)
using JDK 1.7.0_17, Windows 7
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);
}
}
not able to ...., every have got the same Borders, there must be another issue, 1st and 2nd. are editable JComboBoxes
for better help sooner post an SSCCE, short, runnable, compilable, just about two JComboBoxes, Native OS, compiled in JDK, runned in JRE
WinXP Java6
Win7 Java7
Win7 Java6
Win8 Java6
Win8 Java7
from code
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();
}
});
}
}
Related
We are working on a Swing application with Nimbus LaF. We have changed many of the Nimbus defaults (control, text, NimbusLightBackground and so on) to have a dark theme.
Now we have great trouble with the rendering of JLists and JComboBoxes, because the renderer apparently uses the NimbusLightBackground color for the selected text foreground. This results in dark grey text on dark blue background - not good.
I have tried overriding any applicable-seeming key in Nimbus Defaults ("ComboBox:\"ComboBox.listRenderer\"[Selected].textForeground" and suchlike) both globally via UIManager.putDefault() and per-component-overrides, but simply cannot get any change.
Even SwingX Highlighters can't seem to override this behaviour, at least in the combobox dropdown.
Any ideas on how to set the selected text foreground color for J(X)List and J(X)ComboBox Dropdowns?
My latest attempt at per-component-override:
JXComboBox comboBox = new JXComboBox();
UIDefaults comboBoxTheme = new UIDefaults();
comboBoxTheme.put("nimbusLightBackground", new Color(0xFFFAFA));
comboBoxTheme.put("ComboBox:\"ComboBox.listRenderer\"[Selected].textForeground", new Color(0xFFFAFA));
comboBox.putClientProperty("Nimbus.Overrides.InheritDefaults", true);
comboBox.putClientProperty("Nimbus.Overrides", comboBoxTheme);
SwingUtilities.updateComponentTreeUI(comboBox);
And the application-wide nimbus defaults:
ColorUIResource backgroundUI = new ColorUIResource(0x494949);
ColorUIResource textUI = new ColorUIResource(0xFFFAFA);
ColorUIResource controlBackgroundUI = new ColorUIResource(0x5F5F4D);
ColorUIResource infoBackgroundUI = new ColorUIResource(0x2f5cb4);
ColorUIResource infoUI = new ColorUIResource(0x2f5cb4);
ColorUIResource lightBackgroundUI = new ColorUIResource(0x5D5D5B);
ColorUIResource focusUI = new ColorUIResource(0x39698a);
UIManager.put("control", backgroundUI);
UIManager.put("text", textUI);
UIManager.put("nimbusLightBackground", lightBackgroundUI);
UIManager.put("info", infoUI);
UIManager.put("nimbusInfoBlue", infoBackgroundUI);
UIManager.put("nimbusBase", controlBackgroundUI);
UIManager.put("nimbusBlueGrey", controlBackgroundUI);
UIManager.put("nimbusFocus", focusUI);
All implemented in Java 7u55, though I doubt that matters as nobody seems to have maintained Swing/Nimbus for quite some time.
PS: I have, of course, read this question and others, but have not found an answer that works.
EDIT: here is an SSCCE that demonstrates the problem. It creates a JFrame with a default-only combobox on top, a list in the middle and a per-component-overriden combobox at the bottom. The problem can be seen when selecting a value in the list or from the box dropdowns.
package sscce;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.ColorUIResource;
public class ForegroundProblemDemo extends JFrame {
public ForegroundProblemDemo() {
super("Demo");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComboBox<String> comboBoxWithDefaults = createComboBox();
JComboBox<String> comboBoxWithOverrides = createComboBox();
JList<String> list = createList();
addOverrides(comboBoxWithOverrides);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(new JScrollPane(list), BorderLayout.CENTER);
getContentPane().add(comboBoxWithDefaults, BorderLayout.NORTH);
getContentPane().add(comboBoxWithOverrides, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
JComboBox<String> createComboBox() {
JComboBox<String> comboBox = new JComboBox<>(new String[] {"A","B","C","D"});
return comboBox;
}
JList<String> createList() {
JList<String> list = new JList<>(new String[] {"A","B","C","D"});
return list;
}
void addOverrides(JComponent component) {
UIDefaults theme = new UIDefaults();
theme.put("nimbusLightBackground", new Color(0xFFFAFA));
theme.put("ComboBox:\"ComboBox.listRenderer\"[Selected].textForeground", new Color(0xFFFAFA));
component.putClientProperty("Nimbus.Overrides.InheritDefaults", true);
component.putClientProperty("Nimbus.Overrides", theme);
SwingUtilities.updateComponentTreeUI(component);
}
public static void main(String... args) throws Throwable {
ColorUIResource backgroundUI = new ColorUIResource(0x494949);
ColorUIResource textUI = new ColorUIResource(0xFFFAFA);
ColorUIResource controlBackgroundUI = new ColorUIResource(0x5F5F4D);
ColorUIResource infoBackgroundUI = new ColorUIResource(0x2f5cb4);
ColorUIResource infoUI = new ColorUIResource(0x2f5cb4);
ColorUIResource lightBackgroundUI = new ColorUIResource(0x5D5D5B);
ColorUIResource focusUI = new ColorUIResource(0x39698a);
UIManager.put("control", backgroundUI);
UIManager.put("text", textUI);
UIManager.put("nimbusLightBackground", lightBackgroundUI);
UIManager.put("info", infoUI);
UIManager.put("nimbusInfoBlue", infoBackgroundUI);
UIManager.put("nimbusBase", controlBackgroundUI);
UIManager.put("nimbusBlueGrey", controlBackgroundUI);
UIManager.put("nimbusFocus", focusUI);
for (LookAndFeelInfo lafInfo : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(lafInfo.getName())) {
UIManager.setLookAndFeel(lafInfo.getClassName());
break;
}
}
new ForegroundProblemDemo();
}
}
EDIT 2: Sorry, should have mentioned this before: For the list the problem is easily resolved with the setSelectionForeground() method. For ComboBoxes, I have yet to find a way short of custom renderers. So my main focus here is on the ComboBoxes.
see whats happens, Win8.1 64b, Java7, JDK 1.7_021, by using full rectangle Painter,
import java.awt.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;
import javax.swing.plaf.nimbus.AbstractRegionPainter;
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) {
try {
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(laf.getName())) {
UIManager.setLookAndFeel(laf.getClassName());
UIManager.getLookAndFeelDefaults().put("ComboBox[Enabled].backgroundPainter",
new javax.swing.plaf.nimbus.AbstractRegionPainter() {
#Override
protected AbstractRegionPainter.PaintContext getPaintContext() {
return new AbstractRegionPainter.PaintContext(null, null, false);
}
#Override
protected void doPaint(Graphics2D g, JComponent c,
int width, int height, Object[] extendedCacheKeys) {
g.setColor(Color.MAGENTA);
g.fill(new Rectangle(0, 0, width, height));
}
});
UIManager.getLookAndFeelDefaults().put("ComboBox[Focused+Pressed].backgroundPainter",
new javax.swing.plaf.nimbus.AbstractRegionPainter() {
#Override
protected AbstractRegionPainter.PaintContext getPaintContext() {
return new AbstractRegionPainter.PaintContext(null, null, false);
}
#Override
protected void doPaint(Graphics2D g, JComponent c,
int width, int height, Object[] extendedCacheKeys) {
g.setColor(Color.CYAN);
g.fill(new Rectangle(0, 0, width, height));
}
});
UIManager.getLookAndFeelDefaults().put("ComboBox[Focused].backgroundPainter",
new javax.swing.plaf.nimbus.AbstractRegionPainter() {
#Override
protected AbstractRegionPainter.PaintContext getPaintContext() {
return new AbstractRegionPainter.PaintContext(null, null, false);
}
#Override
protected void doPaint(Graphics2D g, JComponent c,
int width, int height, Object[] extendedCacheKeys) {
g.setColor(Color.RED);
g.fill(new Rectangle(0, 0, width, height));
}
});
}
}
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyComboBox aCTF = new MyComboBox();
}
});
}
}
nothing happends without using an XxxRenderer, then is possible to create nice theme for editable and non_editable JComboBox (with the same Color theme)
I'd be look at Seaglas L&F (note to required compiled in JDK 1.6._Xxx)
import java.awt.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.UIManager;
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);
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) {
try {
UIManager.setLookAndFeel("com.seaglasslookandfeel.SeaGlassLookAndFeel");
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyComboBox aCTF = new MyComboBox();
}
});
}
}
I do not like this answer and will gladly accept any one that tells me how it works with just Nimbus settings
What I have ended up doing - and will be delighted to change if I find a better solution - is this:
I have created a ListCellRenderer implementation that wraps the DefaultListCellRenderer and sets the foreground color iff the isSelected parameter is true. It works, but I do not like it one bit for these reasons:
Every other custom renderer (thankfully not many) will have to implement the same hack, which violates the DRY principle.
This overrides the LookAndFeel in such a way that setting another theme (or simply changing back to light theme) will require changes in multiple places in the code.
Every instance of JList or JComboBox will have to set the renderer manually, which again violates the DRY principle.
It is an ugly workaround for a bug in the Java core libraries and I am furious that despite multiple bug reports to that topic nothing seems to have happened since 2007.
Anyway, here's the code for those lonely wanderers who may have the same problem.
import java.awt.Color;
import java.awt.Component;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
#SuppressWarnings("rawtypes")
public class ThemeCompliantListCellRenderer implements ListCellRenderer {
private ListCellRenderer wrappedRenderer = new DefaultListCellRenderer();
private Color textColor = new Color(0xFFFAFA);
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
#SuppressWarnings("unchecked")
Component c = wrappedRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (isSelected) {
c.setForeground(textColor);
}
return c;
}
public void setSelectedForeground(Color color) {
textColor = color;
}
}
I've written a basic DnD program that has four JLabels in a row. I've noticed
that when I drag a label to the left, it is displayed below the next label. However,
when I drag the label to the right, it is displayed above the next label.
The labels are added in order, left to right. So the dragged label is being
displayed below other labels that were added before the dragged label, and displayed
above other labels that were added after the dragged label.
Can anyone explain why this happens? Can anyone offer a fix so that the dragged label
is displayed above the other labels?
Thanks.
source code:
public class LabelDnd extends JPanel {
private JLabel[] labels;
private Color[] colors = { Color.BLUE, Color.BLACK, Color.RED, Color.MAGENTA };
public LabelDnd() {
super();
this.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
this.setBackground(Color.WHITE);
this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
JPanel basePanel = new JPanel();
basePanel.setLayout(new GridLayout(1, 4, 4, 4));
basePanel.setBackground(Color.CYAN);
MouseAdapter listener = new MouseAdapter() {
Point p = null;
#Override
public void mousePressed(MouseEvent e) {
p = e.getLocationOnScreen();
}
#Override
public void mouseDragged(MouseEvent e) {
JComponent c = (JComponent) e.getSource();
Point l = c.getLocation();
Point here = e.getLocationOnScreen();
c.setLocation(l.x + here.x - p.x, l.y + here.y - p.y);
p = here;
}
};
this.labels = new JLabel[4];
for (int i = 0; i < this.labels.length; i++) {
this.labels[i] = new JLabel(String.valueOf(i), JLabel.CENTER);
this.labels[i].setOpaque(true);
this.labels[i].setPreferredSize(new Dimension(100, 100));
this.labels[i].setBackground(this.colors[i]);
this.labels[i].setForeground(Color.WHITE);
this.labels[i].addMouseListener(listener);
this.labels[i].addMouseMotionListener(listener);
basePanel.add(this.labels[i]);
}
this.add(basePanel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("LabelDnd");
frame.getContentPane().setLayout(new BorderLayout());
LabelDnd panel = new LabelDnd();
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
You are not changing the order that the labels have been added or are being painted in your code. Consider elevating the JLabel to the glasspane when dragging (after removing it from the main container), and then re-adding it to the main container on mouse release.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.*;
import java.util.Comparator;
import java.util.PriorityQueue;
import javax.swing.*;
#SuppressWarnings("serial")
public class LabelDnd extends JPanel {
private static final String X_POS = "x position";
private JLabel[] labels;
private Color[] colors = { Color.BLUE, Color.BLACK, Color.RED, Color.MAGENTA };
public LabelDnd() {
super();
// this.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
this.setBackground(Color.WHITE);
this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
JPanel basePanel = new JPanel();
basePanel.setLayout(new GridLayout(1, 4, 4, 4));
basePanel.setBackground(Color.CYAN);
MouseAdapter listener = new MouseAdapter() {
Point loc = null;
Container parentContainer = null;
Container glasspane = null;
JLabel placeHolder = new JLabel("");
private Point glassLocOnScn;
#Override
public void mousePressed(MouseEvent e) {
JComponent selectedLabel = (JComponent) e.getSource();
loc = e.getPoint();
Point currLocOnScn = e.getLocationOnScreen();
parentContainer = selectedLabel.getParent();
JRootPane rootPane = SwingUtilities.getRootPane(selectedLabel);
glasspane = (Container) rootPane.getGlassPane();
glasspane.setVisible(true);
glasspane.setLayout(null);
glassLocOnScn = glasspane.getLocationOnScreen();
Component[] comps = parentContainer.getComponents();
// remove all labels from parent
parentContainer.removeAll();
// add labels back except for selected one
for (Component comp : comps) {
if (comp != selectedLabel) {
parentContainer.add(comp);
} else {
// add placeholder in place of selected component
parentContainer.add(placeHolder);
}
}
selectedLabel.setLocation(currLocOnScn.x - loc.x - glassLocOnScn.x,
currLocOnScn.y - loc.y - glassLocOnScn.y);
glasspane.add(selectedLabel);
glasspane.setVisible(true);
parentContainer.revalidate();
parentContainer.repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
JComponent selectedLabel = (JComponent) e.getSource();
glassLocOnScn = glasspane.getLocationOnScreen();
Point currLocOnScn = e.getLocationOnScreen();
selectedLabel.setLocation(currLocOnScn.x - loc.x - glassLocOnScn.x,
currLocOnScn.y - loc.y - glassLocOnScn.y);
glasspane.repaint();
}
#Override
public void mouseReleased(MouseEvent e) {
JComponent selectedLabel = (JComponent) e.getSource();
if (parentContainer == null || glasspane == null) {
return;
}
// sort the labels based on their x position on screen
PriorityQueue<JComponent> compQueue = new PriorityQueue<JComponent>(
4, new Comparator<JComponent>() {
#Override
public int compare(JComponent o1, JComponent o2) {
// sort of a kludge -- checking a client property that
// holds the x-position
Integer i1 = (Integer) o1.getClientProperty(X_POS);
Integer i2 = (Integer) o2.getClientProperty(X_POS);
return i1.compareTo(i2);
}
});
// sort of a kludge -- putting x position before removing component
// into a client property to associate it with the JLabel
selectedLabel.putClientProperty(X_POS, selectedLabel.getLocationOnScreen().x);
glasspane.remove(selectedLabel);
compQueue.add(selectedLabel);
Component[] comps = parentContainer.getComponents();
for (Component comp : comps) {
JLabel label = (JLabel) comp;
if (!label.getText().trim().isEmpty()) { // if placeholder!
label.putClientProperty(X_POS, label.getLocationOnScreen().x);
compQueue.add(label); // add to queue
}
}
parentContainer.removeAll();
// add back labels sorted by x-position on screen
while (compQueue.size() > 0) {
parentContainer.add(compQueue.remove());
}
parentContainer.revalidate();
parentContainer.repaint();
glasspane.repaint();
}
};
this.labels = new JLabel[4];
for (int i = 0; i < this.labels.length; i++) {
this.labels[i] = new JLabel(String.valueOf(i), JLabel.CENTER);
this.labels[i].setOpaque(true);
this.labels[i].setPreferredSize(new Dimension(100, 100));
this.labels[i].setBackground(this.colors[i]);
this.labels[i].setForeground(Color.WHITE);
this.labels[i].addMouseListener(listener);
this.labels[i].addMouseMotionListener(listener);
basePanel.add(this.labels[i]);
}
this.add(basePanel);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("LabelDnd");
frame.getContentPane().setLayout(new BorderLayout());
LabelDnd panel = new LabelDnd();
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Because of z-index of your Swing component. You should use setComponentZOrder to change component's z-index value after you drag.
Please check this link to get more details
I have a JPanel which contains a JToolbar (including few buttons without text) and a JTable and I need to enable/disable (make internal widgets not clickable). I tried this:
JPanel panel = ....;
for (Component c : panel.getComponents()) c.setEnabled(enabled);
but it doesn't work. Is there a better and more generic solution to enable/disable all internal components in a JPanel?
I have partially solved my problem using JLayer starting from the example here http://docs.oracle.com/javase/tutorial/uiswing/misc/jlayer.html:
layer = new JLayer<JComponent>(myPanel, new BlurLayerUI(false));
.....
((BlurLayerUI)layer.getUI()).blur(...); // switch blur on/off
class BlurLayerUI extends LayerUI<JComponent> {
private BufferedImage mOffscreenImage;
private BufferedImageOp mOperation;
private boolean blur;
public BlurLayerUI(boolean blur) {
this.blur = blur;
float ninth = 1.0f / 9.0f;
float[] blurKernel = {
ninth, ninth, ninth,
ninth, ninth, ninth,
ninth, ninth, ninth
};
mOperation = new ConvolveOp(
new Kernel(3, 3, blurKernel),
ConvolveOp.EDGE_NO_OP, null);
}
public void blur(boolean blur) {
this.blur=blur;
firePropertyChange("blur", 0, 1);
}
#Override
public void paint (Graphics g, JComponent c) {
if (!blur) {
super.paint (g, c);
return;
}
int w = c.getWidth();
int h = c.getHeight();
if (w == 0 || h == 0) {
return;
}
// Only create the offscreen image if the one we have
// is the wrong size.
if (mOffscreenImage == null ||
mOffscreenImage.getWidth() != w ||
mOffscreenImage.getHeight() != h) {
mOffscreenImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
}
Graphics2D ig2 = mOffscreenImage.createGraphics();
ig2.setClip(g.getClip());
super.paint(ig2, c);
ig2.dispose();
Graphics2D g2 = (Graphics2D)g;
g2.drawImage(mOffscreenImage, mOperation, 0, 0);
}
#Override
public void applyPropertyChange(PropertyChangeEvent pce, JLayer l) {
if ("blur".equals(pce.getPropertyName())) {
l.repaint();
}
}
}
I still have 2 problems:
In the link above events are relative to mouse only. How can I manage the keyboard events?
How can I create a "gray out" effect in place of blur?
It requires a recursive call.
import java.awt.*;
import javax.swing.*;
public class DisableAllInContainer {
public void enableComponents(Container container, boolean enable) {
Component[] components = container.getComponents();
for (Component component : components) {
component.setEnabled(enable);
if (component instanceof Container) {
enableComponents((Container)component, enable);
}
}
}
DisableAllInContainer() {
JPanel gui = new JPanel(new BorderLayout());
final JPanel container = new JPanel(new BorderLayout());
gui.add(container, BorderLayout.CENTER);
JToolBar tb = new JToolBar();
container.add(tb, BorderLayout.NORTH);
for (int ii=0; ii<3; ii++) {
tb.add(new JButton("Button"));
}
JTree tree = new JTree();
tree.setVisibleRowCount(6);
container.add(new JScrollPane(tree), BorderLayout.WEST);
container.add(new JTextArea(5,20), BorderLayout.CENTER);
final JCheckBox enable = new JCheckBox("Enable", true);
enable.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
enableComponents(container, enable.isSelected());
}
});
gui.add(enable, BorderLayout.SOUTH);
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
new DisableAllInContainer();
}
});
}}
I used the following function:
void setPanelEnabled(JPanel panel, Boolean isEnabled) {
panel.setEnabled(isEnabled);
Component[] components = panel.getComponents();
for(int i = 0; i < components.length; i++) {
if(components[i].getClass().getName() == "javax.swing.JPanel") {
setPanelEnabled((JPanel) components[i], isEnabled);
}
components[i].setEnabled(isEnabled);
}
}
you can overlay whole Container / JComponent
GlassPane block by default MouseEvents, but not Keyboard, required consume all keyevents from ToolKit
JLayer (Java7) based on JXLayer (Java6)
can't see reason(s) why not works for you
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class AddComponentsAtRuntime {
private JFrame f;
private JPanel panel;
private JCheckBox checkValidate, checkReValidate, checkRepaint, checkPack;
public AddComponentsAtRuntime() {
JButton b = new JButton();
//b.setBackground(Color.red);
b.setBorder(new LineBorder(Color.black, 2));
b.setPreferredSize(new Dimension(600, 20));
panel = new JPanel(new GridLayout(0, 1));
panel.add(b);
f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(panel, "Center");
f.add(getCheckBoxPanel(), "South");
f.setLocation(200, 200);
f.pack();
f.setVisible(true);
}
private JPanel getCheckBoxPanel() {
checkValidate = new JCheckBox("validate");
checkValidate.setSelected(false);
checkReValidate = new JCheckBox("revalidate");
checkReValidate.setSelected(true);
checkRepaint = new JCheckBox("repaint");
checkRepaint.setSelected(true);
checkPack = new JCheckBox("pack");
checkPack.setSelected(true);
JButton addComp = new JButton("Add New One");
addComp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JButton b = new JButton();
//b.setBackground(Color.red);
b.setBorder(new LineBorder(Color.black, 2));
b.setPreferredSize(new Dimension(400, 10));
panel.add(b);
makeChange();
System.out.println(" Components Count after Adds :" + panel.getComponentCount());
}
});
JButton removeComp = new JButton("Remove One");
removeComp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int count = panel.getComponentCount();
if (count > 0) {
panel.remove(0);
}
makeChange();
System.out.println(" Components Count after Removes :" + panel.getComponentCount());
}
});
JButton disabledComp = new JButton("Disabled All");
disabledComp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Component c : panel.getComponents()) {
c.setEnabled(false);
}
}
});
JButton enabledComp = new JButton("Enabled All");
enabledComp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (Component c : panel.getComponents()) {
c.setEnabled(true);
}
}
});
JPanel panel2 = new JPanel();
panel2.add(checkValidate);
panel2.add(checkReValidate);
panel2.add(checkRepaint);
panel2.add(checkPack);
panel2.add(addComp);
panel2.add(removeComp);
panel2.add(disabledComp);
panel2.add(enabledComp);
return panel2;
}
private void makeChange() {
if (checkValidate.isSelected()) {
panel.validate();
}
if (checkReValidate.isSelected()) {
panel.revalidate();
}
if (checkRepaint.isSelected()) {
panel.repaint();
}
if (checkPack.isSelected()) {
f.pack();
}
}
public static void main(String[] args) {
AddComponentsAtRuntime makingChanges = new AddComponentsAtRuntime();
}
}
#Kesavamoorthi
if you want to make it more general:
void setPanelEnabled(java.awt.Container cont, Boolean isEnabled) {
cont.setEnabled(isEnabled);
java.awt.Component[] components = cont.getComponents();
for (int i = 0; i < components.length; i++) {
if (components[i] instanceof java.awt.Container) {
setPanelEnabled((java.awt.Container) components[i], isEnabled);
}
components[i].setEnabled(isEnabled);
}
}
I have this following combo box, where i am able to create my combo box with items etc, but the look is not same as JTextField. How can i make JCombobox look same like JTextField?
MyComboBox.java:
import java.awt.Color;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.plaf.basic.BasicComboBoxUI;
public class MyComboBox extends JComboBox {
public MyComboBox(String[] name) {
Border border = BorderFactory.createEmptyBorder(11, 11, 11, 11);
JComboBox cb = new JComboBox(name);
cb.setUI(new BasicComboBoxUI() {
#Override
protected JButton createArrowButton() {
return new JButton() {
#Override
public int getWidth() {
return 0;
}
};
}
});
setModel(cb.getModel());
setOpaque(false);
setBorder(new LineBorder(Color.black, 1, true));
//setBackground(Color.white);
setVisible(true);
}
// public void paintComponent(Graphics g) {
// super.paintComponent(g);
// g.setColor(new Color(red, green, blue) );
// g.fillOval(125, 125, 50, 50);
// }
}
best of all could be use Look and Feels
JComboBox has two states, JComboBox can be Editable and Non_Editable (default)
without CustomUI (as example by #aterai), but Look and Feel sensitive, only for Metal Look and Feel
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();
}
});
}
}
I guess you are meaning RoundedCornerBorder:
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
public class RoundedComboBoxTest {
public JComponent makeUI() {
UIManager.put("Panel.background", Color.GRAY);
UIManager.put("ComboBox.foreground", Color.BLACK);
UIManager.put("ComboBox.background", Color.GRAY);
UIManager.put("ComboBox.selectionForeground", Color.WHITE);
UIManager.put("ComboBox.selectionBackground", Color.GRAY);
UIManager.put("ComboBox.buttonDarkShadow", Color.BLACK);
UIManager.put("ComboBox.border", new RoundedCornerBorder());
DefaultComboBoxModel<String> m = new DefaultComboBoxModel<>();
m.addElement("1234");
m.addElement("5555555555555555555555");
m.addElement("6789000000000");
JComboBox<String> combo = new JComboBox<>(m);
combo.setUI(new BasicComboBoxUI() {
#Override protected JButton createArrowButton() {
JButton b = super.createArrowButton();
b.setContentAreaFilled(false);
b.setBackground(Color.GRAY);
b.setBorder(BorderFactory.createEmptyBorder());
return b;
}
});
Object o = combo.getAccessibleContext().getAccessibleChild(0);
((JComponent)o).setBorder(
BorderFactory.createMatteBorder(0,1,1,1,Color.BLACK));
JPanel p = new JPanel(new BorderLayout());
p.add(combo, BorderLayout.NORTH);
p.setOpaque(true);
p.setBackground(Color.GRAY);
p.setBorder(BorderFactory.createEmptyBorder(15,15,15,15));
return p;
}
public static void main(String[] args) {
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 RoundedComboBoxTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class RoundedCornerBorder extends AbstractBorder {
#Override public void paintBorder(
Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D)g.create();
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int r = 12;
Area round = new Area(
new RoundRectangle2D.Float(x, y, width-1, height-1, r, r));
Rectangle b = round.getBounds();
b.setBounds(b.x, b.y + r, b.width, b.height - r);
round.add(new Area(b));
Container parent = c.getParent();
if(parent!=null) {
g2.setColor(parent.getBackground());
Area corner = new Area(new Rectangle2D.Float(x, y, width, height));
corner.subtract(round);
g2.fill(corner);
}
g2.setColor(Color.BLACK);
g2.draw(round);
g2.dispose();
}
#Override public Insets getBorderInsets(Component c) {
return new Insets(4, 8, 4, 8);
}
#Override public Insets getBorderInsets(Component c, Insets insets) {
insets.left = insets.right = 8;
insets.top = insets.bottom = 4;
return insets;
}
}
You will have to define your own custom renderer, check out this tutorial as how to define one.
You can also set your background and foreground in your MyComboBox.java but that will not have an impact on selected item foreground, background.
I wrote a program which create a Frame which will display a Control panel and Visual panel.But buttons in control panel is taking too much space. So any body has any idea how to fix it ?? Given is the code.
import java.awt.*;
import java.awt.event.KeyEvent;
import javax.swing.*;
/**
* This class generates and displays a visualization of a Sierpinski
*
*/
public class tOpost
{
private JFrame window;
private JTextField depthTextField;
private Canvas visual;
// declare and initialize default values
private int canvasSize = 512;
/**
* Creates a new window and displays a visualization of a Mandelbrot set
*/
public tOpost()
{
// create new window
window = new JFrame("Sierpinski Visulaizer");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setLayout(new FlowLayout(FlowLayout.LEFT));
// create main panel
JPanel mainPanel = new JPanel(new GridLayout(0,1));
// create textfields with labels
JPanel depthField = new JPanel(new FlowLayout());
depthField.add(new JLabel("Recursive Depth: "));
depthTextField = new JTextField("");
depthTextField.setPreferredSize(new Dimension(80,25));
depthField.add(depthTextField);
// create comboBoxes
JPanel panel2 = new JPanel();
String[] colorText= {"Blue", "Green"};
panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
JPanel[] jPanels = new JPanel[5];
for (int i = 0; i<5; i++) {
JPanel depthColorPanel = new JPanel();
depthColorPanel.add(new JLabel("Color " + (i + 1) + ": "));
JComboBox comboBox = new JComboBox(colorText);
comboBox.setSelectedItem("Blue");
depthColorPanel.add(comboBox);
jPanels[i] = depthColorPanel;
}
JPanel randomColorPanel = new JPanel();
JCheckBox randomColorButton = new JCheckBox("Randomize color at each level");
randomColorButton.setMnemonic(KeyEvent.VK_G);
randomColorButton.setSelected(false);
randomColorPanel.add(randomColorButton);
// create panel for controls
panel2.add(depthField);
for (JPanel panel : jPanels) {
panel2.add(panel);
}
panel2.add(randomColorPanel);
// create button
JPanel germinatePanel = new JPanel(new FlowLayout());
JButton germinateButton = new JButton("Draw");
germinatePanel.add(germinateButton);
mainPanel.add(panel2);
mainPanel.add(germinatePanel);
// create canvas for visualization
visual = new Canvas();
visual.setBackground(Color.BLACK);
visual.setPreferredSize(new Dimension(canvasSize, canvasSize));
mainPanel.setMinimumSize(new Dimension(100, 100));
mainPanel.setPreferredSize(new Dimension(250,canvasSize));
mainPanel.setLocation(750, 250);
// pack widgets and display window
window.add(visual);
window.add(mainPanel);
window.pack();
window.setVisible(true);
System.out.println(mainPanel.getSize().getHeight()+","+ mainPanel.getSize().getWidth());
}
/**
* Draws Triangle.
*
* #param x
* #param y
* #param s
* #param color
*/
/**
* Starts the program by creating a new instance of the Triangle class.
*/
public static void main(String[] args)
{
new tOpost();
}
}
don't mixing AWT Components with Swing JComponents, since is possible, but still caused with a few issues
don't declare for mainPanel.setSize(100,100);, let this is job for proper LayoutManager
JPanel depthField = new JPanel(new FlowLayout());, FlowLayout accepting PreferredSize that came from JComponents
panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS)); BoxLayout accepting PreferredSize that returns JComponents
JPanel has implemented FlowLayout by default (without any definitions of LayoutManager)
you have to override proper method for Painting in the standard Java GUI
for AWT Components use method paint()
for Swing JComponents use method paintComponent()
.
.
EDIT
.
.
this code will help you with workaround for JComboBox
code
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ComboBoxEditor;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.border.LineBorder;
import javax.swing.event.EventListenerList;
class ColorComboBoxEditor implements ComboBoxEditor {
final protected JButton editor;
private EventListenerList listenerList = new EventListenerList();
ColorComboBoxEditor(Color initialColor) {
editor = new JButton("");
editor.setBackground(initialColor);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Color currentBackground = editor.getBackground();
Color color = JColorChooser.showDialog(editor, "Color Chooser", currentBackground);
if ((color != null) && (currentBackground != color)) {
editor.setBackground(color);
fireActionEvent(color);
}
}
};
editor.addActionListener(actionListener);
}
#Override
public void addActionListener(ActionListener l) {
listenerList.add(ActionListener.class, l);
}
#Override
public Component getEditorComponent() {
return editor;
}
#Override
public Object getItem() {
return editor.getBackground();
}
#Override
public void removeActionListener(ActionListener l) {
listenerList.remove(ActionListener.class, l);
}
#Override
public void selectAll() {
}
#Override
public void setItem(Object newValue) {
if (newValue instanceof Color) {
Color color = (Color) newValue;
editor.setBackground(color);
} else {
try {
Color color = Color.decode(newValue.toString());
editor.setBackground(color);
} catch (NumberFormatException e) {
}
}
}
protected void fireActionEvent(Color color) {
Object listeners[] = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ActionListener.class) {
ActionEvent actionEvent = new ActionEvent(editor, ActionEvent.ACTION_PERFORMED, color.toString());
((ActionListener) listeners[i + 1]).actionPerformed(actionEvent);
}
}
}
}
class ColorCellRenderer implements ListCellRenderer {
private DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
private final static Dimension preferredSize = new Dimension(0, 20);
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Color) {
renderer.setBackground((Color) value);
}
if (cellHasFocus || isSelected) {
renderer.setBorder(new LineBorder(Color.DARK_GRAY));
} else {
renderer.setBorder(null);
}
renderer.setPreferredSize(preferredSize);
return renderer;
}
}
class ColorComboBoxEditorRendererDemo {
public ColorComboBoxEditorRendererDemo() {
Color colors[] = {Color.BLACK, Color.BLUE, Color.GREEN, Color.RED, Color.WHITE, Color.YELLOW};
JFrame frame = new JFrame("Color JComboBox");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JComboBox comboBox = new JComboBox(colors);
comboBox.setEditable(true);
comboBox.setRenderer(new ColorCellRenderer());
Color color = (Color) comboBox.getSelectedItem();
ComboBoxEditor editor = new ColorComboBoxEditor(color);
comboBox.setEditor(editor);
frame.add(comboBox, BorderLayout.NORTH);
final JLabel label = new JLabel();
label.setOpaque(true);
label.setBackground((Color) comboBox.getSelectedItem());
frame.add(label, BorderLayout.CENTER);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent actionEvent) {
Color selectedColor = (Color) comboBox.getSelectedItem();
label.setBackground(selectedColor);
}
};
comboBox.addActionListener(actionListener);
frame.setSize(300, 200);
frame.setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ColorComboBoxEditorRendererDemo colorComboBoxEditorRendererDemo = new ColorComboBoxEditorRendererDemo();
}
});
}
}