I spent the last few hours looking for a solution or at least a decent guide about this issue, but found nothing.
I'm implementing a custom Swing Look and Feel for a small GUI of mine. Up until now I've been using the UIManager.put("key", values); method to good success, but I got stuck when it came to properly modify JComboBoxes.
Using this list I managed to get my jComboBoxes really close to what I want them to look like:
I have two issues with this, a major and a minor one:
Major
I want the blue shown border gone.
Minor
I'd really like the black shown border gone.
Apparently no key in the UIDefaults has anything to do with either two borders: they seem somehow hardcoded in the Look and Feel I'm modifying (which should be Metal). I resorted to manually extending the ComboBoxRenderer and managed to come up with this:
package exec.laf.theme;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
public class ComboBoxRenderer extends BasicComboBoxRenderer {
private Color background;
private Color selectionBackground;
public ComboBoxRenderer() {
super();
background = UIManager.getColor("ComboBox.background");
selectionBackground = UIManager.getColor("ComboBox.selectionBackground");
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setText((String) value);
if (isSelected) setBackground(selectionBackground);
else setBackground(background);
return this;
}
}
Where I specify this Renderer every time I create a JComboBox like so:
aComboBox.setRenderer(new ComboBoxRenderer());
obtaining the same look as the non-extended JComboBox.
The problem is that with this extension I can't find a way of touching those borders. Adding setBorder(new EmptyBorder(0, 0, 0, 0)); accomplishes nothing, since it simply adds a border to the listed items.
I checked the source code for javax.swing.plaf.basic.BasicComboBoxRenderer to see if any borders were applied there, but found nothing (the only border there is the one applied to the listed items, that I can override as shown above.
What am I supposed to do? Am I extending the wrong class, or am I missing something else?
The solution I found is:
UIManager.put("ComboBox.borderPaintsFocus", Boolean.TRUE)
This sets a boolean inside the ComboBoxUI that prevents rendering of the focus border, which is the border painted around all buttons when they are focused. Its style is dependent on your look and feel.
To remove the black border of comboBox PopUp,
Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
BasicComboPopup popup = (BasicComboPopup)child;
popup.setBorder(BorderFactory.createEmptyBorder());
If i understoud, your problem is in generally how to use extended class from BasicComboBoxRenderer. So here a simple code to explain you how to use it:
public class RenderComboBox extends BasicComboBoxRenderer {
Color selectedBackground;
Color selectedForground;
Color background;
Color forground;
public RenderComboBox() {
setOpaque(true);
background = new Color(37, 37, 37);
selectedBackground = new Color(93, 93, 93);
forground = Color.WHITE;
selectedForground = forground;
}
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (isSelected) {
setBackground(selectedBackground);
setForeground(selectedForground);
} else {
setBackground(background);
setForeground(forground);
}
setFont(list.getFont());
if (value == null) {
setText("");
} else {
setText(value.toString());
}
return this;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setLayout(null);
frame.setPreferredSize(new Dimension(200, 170));
JComboBox<String> combobox = new JComboBox<>();
combobox.setRenderer(new RenderComboBox());
combobox.setBounds(50, 50, 100, 20);
combobox.addItem("TEST");
combobox.addItem("REVERT");
frame.add(combobox);
frame.pack();
frame.setVisible(true);
}
}
Related
I have this code and MyComboBoxRenderer() seems to not work with it. It has an error in the line with comment written below.
This code is made for autosuggest. So it shows suggestion in a combobox while user types on the textfield.
public test2() {
initComponents();
jComboBox1.setRenderer(new MyComboBoxRenderer1());
jComboBox1.setBackground(new Color(0,0,0,0));
final JTextField textfield = (JTextField) jComboBox1.getEditor().getEditorComponent(); //it has error in this line
textfield.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
comboFilter(textfield.getText());
}
});
}
});
}
Maybe it has something to do with the textfield. My problem is that I wanted to edit the appearance or design of combobox. I want it to inherit the background of the frame. Like transparent. Example are in the pictures.
Here are the pictures. Please click the links below to see it.
It should be something like this
Rather than this one. This is the output of the codes above.
And here is the code I have in my combobox renderer.
public MyComboBoxRenderer1(){
setOpaque(true);
setFont(new Font ("Segoe UI Semibold", Font.PLAIN ,14));
setForeground(Color.WHITE);
}
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setText(value.toString());
if (isSelected)
{
setBackground(Color.WHITE);
setForeground(Color.BLACK);
}
else {
setBackground(Color.GRAY);
setForeground(Color.WHITE);
}
return this;
}
}
Why is it that the renderer doesn't work with this? And what should I do to make it work? Can anyone help me please? Thank you in advance. :)
EDITED...
I've already set the background transparent. I just need to declare the background of the texfield. XD Yey.
textfield.setBackground(new Color(0,0,0,0));
textfield.setForeground(new Color(255,255,255));
But it left small portion that is still not transparent.
I tried doing an additional comboBox on my frame. But it is without the textfield. And it works just fine!
The upper is the comboBox with textfield, the one I have problem with. The lower is the one w/o textfield, I just tried if the code will work with a normal comboBox. I need to make it look like the lower one.
jComboBox1.setRenderer(new MyComboBoxRenderer1());
jComboBox1.setBackground(new Color(0,0,0,0));
jComboBox2.setRenderer(new MyComboBoxRenderer1());
jComboBox2.setBackground(new Color(0,0,0,0));
It has the same code. But it doesn't work with the other one. Maybe it's because of the textfield again?? :(((
jComboBox1.setBackground(new Color(0,0,0,0));
Don't try to use transparent colors. Swing does not know how to paint transparent colors properly. See: Background With Transparency for more information.
Instead you change the opaqueness of the component:
component.setOpaque( false );
In the case of the combo box you need to worry about the component and the renderer, so you might use:
comboBox.setOpaque(false);
((JLabel)comboBox.getRenderer()).setOpaque(false);
However, this will now cause a problem with the dropdown list. Since the rendering is now transparent you won't see the row selections.
Haven't tested this but a possible solution if to alter the opaqueness of the renderer based on the item being rendered.
The code might be:
public Component getListCellRendererComponent(
JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
setOpaque(index == -1 ? false : true);
// add custom painting here
return this;
}
The -1 indicates the item in the combo box is being rendered as oppose to an item in the list.
When a JComboBox is just made and added and all the background of the selected item is just normal and white:
(ignore the enormous spacing after the text)
When I then open the list and hover my cursor over an item, that item get's highlighted, all normal, nothing wrong with it.
But the problem now is that the highlighting stays once I've clicked on an item:
So my question is:
How can I make the highlighting go away?
Preferably without doing difficult with packages from the community or overloading or whatever.
If I'm right it has to be in the 'root' of the action listener of the combo box?
So:
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == comboBox)
{
// code to delete the highlighting
}
}
The highlighting is done by the default renderer for the combo box.
See the section from the Swing tutorial on Providing Custom Renderers for an example of providing your own custom renderer. You will just want a renderer that doesn't change the background/foreground depending on the selected value.
To make it easier for people with a similar problem, here is the code for the renderer I wrote:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class ComboBoxRenderer extends JLabel implements ListCellRenderer
{
private boolean colorSet;
private Color selectionBackgroundColor;
public ComboBoxRenderer()
{
setOpaque(true);
setHorizontalAlignment(LEFT);
setVerticalAlignment(CENTER);
colorSet = false;
selectionBackgroundColor = Color.red; // Have to set a color, else a compiler error will occur
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
// Check if color is set (only runs the first time)
if(!colorSet)
{
// Set the list' background color to original selection background of the list
selectionBackgroundColor = list.getSelectionBackground();
// Do this only one time since the color will change later
colorSet = true;
}
// Set the list' background color to white (white will show once selection is made)
list.setSelectionBackground(Color.white);
// Check which item is selected
if(isSelected)
{
// Set background color of the item your cursor is hovering over to the original background color
setBackground(selectionBackgroundColor);
}
else
{
// Set background color of all other items to white
setBackground(Color.white);
}
// Do nothing about the text and font to be displayed
setText((String)value);
setFont(list.getFont());
return this;
}
}
Edit: Previous code didn't seem to work as properly, code updated and should work all fine now
Good morning, please,could you mind helping me in determining why this ListCellRenderer class not setting the image icon at combobox cells:
here's the ListCellRenderer class:
class MyComboRendere implements ListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = new JLabel();
label.setOpaque(true);
label.setText(value.toString());
label.setIcon(new ImageIcon("/pics/Color-icon.png"));
if (isSelected)
if (index == 0)
label.setBackground(Color.RED);
else if (index == 1)
label.setBackground(Color.GREEN);
else
label.setBackground(Color.BLUE);
return label;
}
}
and this is a method to setup the combobox:
public void setComboColor(){
Vector<String> colors=new Vector<>();
comboPanel=new JPanel(new BorderLayout());
colors.add("RED");
colors.add("GREEN");
colors.add("BLUE");
colorCombo=new JComboBox(colors);
colorCombo.setRenderer(new MyComboRendere());
comboPanel.add(colorCombo,BorderLayout.BEFORE_FIRST_LINE);
}
It seems that label.setIcon(new ImageIcon("/pics/Color-icon.png")); doesn't get the actual path of the icon as it always returns null, but it doesn't throw an exception. So I tried to use this:
java.net.URL imgURL = getClass().getResource("/pics/Color-icon.png");
label.setIcon(icon);
and it works properly
"/pics/Color-icon.png"
Does this exist? ImageIcon won't throw any exceptions if it fails to load the image, but will return null.
don't provide FileIO inside XxxRenderer, load all Icons to local variable, test for null value
XxxRenderer firing a lots of event (mouse, keys and internally implemented in API), then you recreated Icon on fly
read Oracle tutorial about JComboBox, try code example about similair issue
I have a JTable that is wider than the JScrollPane it is contained in (essentially defined like this):
JTable table = new JTable(model);
// I change some things like disallowing reordering, resizing,
// disable column selection, etc.
// I set the default renderer to a DefaultTableCellRenderer
// getTableCellRendererComponent, and then changes the color
// of the cell text depending on the cell value
JPanel panel = new JPanel(new BorderLayout(0, 5));
panel.add(new JScrollPane(table), BorderLayout.CENTER);
// add other stuff to the panel
this.add(panel, BorderLayout.CENTER);
Before I changed the look and feel from the default to Nimbus, I was able to scroll left and right in the JTable. (I like the Mac LaF, but it isn't supported on Windows, and the Windows LaF is ugly in my opinion),
I took the following code straight from the Java Tutorials:
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
// If Nimbus is not available, you can set the GUI to another look
// and feel.
}
I recompiled and ran the code without changing any of the table definition stuff above, and I couldn't scroll horizontally in the JTable anymore.
I can't seem to find anything on what would cause this. Is this the normal behavior for Nimbus, or can I change it? If so, how? or should I just try a different look and feel?
EDIT:
I discovered two things:
I made a new class extending JTable to test this. I copied the code for getScrollableUnitIncrement from the JTable source, and added print statements. The orientation that is passed seems to always be SwingConstants.VERTICAL, while in the default Look and Feel (Mac Aqua or whatever), both horizontal and vertical scrolling works. I don't know why this is.
Another part of the project also relies on horizontal scrolling. I tested it with both LaFs, and it worked fine in the default, but Nimbus would not allow me to scroll horizontally, either.
Could this be a bug with Nimbus?
Either way, I guess I'm going to use a different Look and Feel...
EDIT #2:
I should have mentioned this before. I am able to scroll horizontally with the scroll bar in the window, but not with my track pad or scroll wheel on my mouse.
(Note: After writing this, I found a solution, which appears in the addendum of this post.)
To reproduce the problem, you need to make the scroll bars required. (This is why some people have trouble reproducing this bug.) This means the obvious workaround is to make your horizontal scroll bar optional. (This is not always practical.)
You will only see the bug when you drag the window's width out to more than 1200 pixels or so. Until then, the scroll bar will work fine.
And the problem only shows up in Nimbus. (It may show up in other L&Fs created from the SynthLookAndFeel, but I haven't investigated that yet.)
I've found that the spurious scroll bar thumb only shows up when you have no need to scroll, so it's just a visual bug. When you need to scroll, the scroll bar thumb will appear and will work properly, although it might not be the right size. This may be why it hasn't been fixed yet.
Here's an example where you can compare the different L&Fs. In this example, Choose Nimbus, then drag the width inward and watch how the size of the scroll bar changes. When you're wider than the background image, the spurious scroll bar will be visible. As soon as you get narrower, a valid scroll bar thumb will appear, but it will be a bit too small. As you get smaller, the scroll bar thumb will stay a constant size until you reach a certain point, (at viewport width of 1282 pixels) then it will start getting smaller like it's supposed to.
With any other L&F, as soon as you get narrower than the background image, a thumb will appear that almost fills its space. It gets smaller as the window gets smaller, like it's supposed to.
(This exercise will also reveal how Nimbus draws much more slowly than any other L&F.)
You can observe different, but still incorrect behavior by making the icon smaller. Try 800 x 450. The spurious scroll bar will appear when the viewport width is > 1035. (Viewport size is shown at the bottom of the window.)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* NimbusScrollBug
* <p/>
* #author Miguel Muñoz
*/
public class NimbusScrollBug extends JPanel {
private static final long serialVersionUID = -4235866781219951631L;
private static JFrame frame;
private static boolean firstTime = true;
private static Point location;
private static final UIManager.LookAndFeelInfo[] INFOS
= UIManager.getInstalledLookAndFeels();
private final JLabel viewPortLabel = new JLabel();
public static void main(final String[] args) {
makeMainFrame(new NimbusScrollBug(), "System");
}
public static void makeMainFrame(final NimbusScrollBug mainPanel,
final String name) {
if (firstTime) {
installLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
frame = new JFrame(name);
final Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(mainPanel, BorderLayout.CENTER);
contentPane.add(makeButtonPane(mainPanel), BorderLayout.LINE_START);
frame.setLocationByPlatform(firstTime);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setVisible(true);
if (firstTime) {
location = frame.getLocation();
} else {
frame.setLocation(location);
}
frame.addComponentListener(new ComponentAdapter() {
#Override
public void componentMoved(final ComponentEvent e) {
location = e.getComponent().getLocation();
}
});
firstTime = false;
}
private static JPanel makeButtonPane(final NimbusScrollBug mainPanel) {
JPanel innerButtonPanel = new JPanel(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0; // forces vertical layout.
for (final UIManager.LookAndFeelInfo lAndF : INFOS) {
final JButton button = new JButton(lAndF.getName());
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
frame.dispose();
installLookAndFeel(lAndF.getClassName());
makeMainFrame(new NimbusScrollBug(), lAndF.getName());
}
});
innerButtonPanel.add(button, constraints);
}
final String version = System.getProperty("java.version");
JLabel versionLabel = new JLabel("Java Version " + version);
innerButtonPanel.add(versionLabel, constraints);
JPanel outerButtonPanel = new JPanel(new BorderLayout());
outerButtonPanel.add(innerButtonPanel, BorderLayout.PAGE_START);
return outerButtonPanel;
}
private static void installLookAndFeel(final String className) {
//noinspection OverlyBroadCatchBlock
try {
UIManager.setLookAndFeel(className);
} catch (Exception e) {
//noinspection ProhibitedExceptionThrown
throw new RuntimeException(e);
}
}
private NimbusScrollBug() {
Icon icon = new Icon() {
#Override
public void paintIcon(final Component c, final Graphics g,
final int x, final int y) {
Graphics2D g2 = (Graphics2D) g;
g2.translate(x, y);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Stroke lineStroke = new BasicStroke(6.0f);
g2.setStroke(lineStroke);
g2.setColor(Color.white);
g2.fillRect(0, 0, getIconWidth(), getIconHeight());
g2.setColor(Color.RED);
g2.drawLine(0, 0, getIconWidth(), getIconHeight());
g2.drawLine(0, getIconHeight(), getIconWidth(), 0);
g2.dispose();
}
#Override
public int getIconWidth() {
return 1600;
}
#Override
public int getIconHeight() {
return 900;
}
};
JLabel label = new JLabel(icon);
setLayout(new BorderLayout());
final JScrollPane scrollPane = new JScrollPane(label,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
label.addHierarchyBoundsListener(new HierarchyBoundsAdapter() {
#Override
public void ancestorResized(final HierarchyEvent e) {
viewPortLabel.setText("ViewPort Size: "
+ scrollPane.getViewport().getSize());
}
});
add(scrollPane, BorderLayout.CENTER);
add(viewPortLabel, BorderLayout.PAGE_END);
}
}
Addendum: Further investigation revealed the problem. The NimbusDefaults class, which creates the UIDefaults instance for Nimbus, has this line:
d.put("ScrollBar.maximumThumbSize", new DimensionUIResource(1000, 1000));
Any other look and feel uses 4096 for both values (so, for really big monitors, they will show the same behavior).
The following method, which may be used to install any look and feel, will fix this problem:
private static void installLookAndFeel(final String className) {
//noinspection OverlyBroadCatchBlock
try {
Class<?> lnfClass = Class.forName(className, true,
Thread.currentThread().getContextClassLoader());
final LookAndFeel lAndF;
lAndF = (LookAndFeel) lnfClass.getConstructor().newInstance();
// Reset the defaults after instantiating, but before
// calling UIManager.setLookAndFeel(). This fixes the Nimbus bug
DimensionUIResource dim = new DimensionUIResource(4096, 4096);
lAndF.getDefaults().put("ScrollBar.maximumThumbSize", dim);
UIManager.setLookAndFeel(lAndF);
} catch (Exception e) {
final String systemName = UIManager.getSystemLookAndFeelClassName();
// Prevents an infinite recursion that's not very likely...
// (I like to code defensively)
if (!className.equals(systemName)) {
installLookAndFeel(systemName);
} else {
// Feel free to handle this any other way.
//noinspection ProhibitedExceptionThrown
throw new RuntimeException(e);
}
}
}
Of course, you can fix the problem for really big monitors by using a bigger value.
I confirmed that the vertical scroll bar has exactly the same problem, but is only seen when the window gets very large vertically. This is why this problem is usually only seen with the horizontal scroll bar.
Based on the information you provided, I'm not able to recreate your problem (and therefore not able to help you figure out what's going wrong). Here's a sscce that works for me. Can you reproduce the problem with this example? Perhaps the problem is trickling down from a different part of the application.
public static void main(String[] args){
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
// If Nimbus is not available, you can set the GUI to another look and feel.
}
//Create Frame
JFrame frame = new JFrame("Title");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create Table
JTable table = new JTable(0, 2);
((DefaultTableModel) table.getModel()).addRow(new Object[]{"Sample Text", "Hi Mom!"});
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
// Wrap table in Scroll pane and add to frame
frame.add(new JScrollPane(table), BorderLayout.CENTER);
// Finish setting up the frame and display
frame.setBounds(0, 0, 600,400);
frame.setPreferredSize(new Dimension(600, 400));
frame.pack();
frame.setVisible(true);
}
I am trying to change the background color of my tabs in a JTabbedPane. I tried JTabbedPane.setBackgroudAt(0, Color.GRAY) and JTabbedPane.setBackgroud(Color.GRAY) and the foreground too, but nothing happens. I changed the background of the panel inside the tab, still nothing.
Edit 1: I'm using UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); if this can help with the solution
Edit 2: Link to a example, https://www.dropbox.com/s/0krn9vikvkq46mz/JavaApplication4.rar
You can change the background color of the tab using setBackgroundAt(), as shown here.
You can change the background color of the tab's content using setBackground(), as shown here. Typically you have to do this on the tab's content, as the enclosing JTabbedPane background color is obscured by the content.
If you still have trouble, please edit your question to include an sscce based on either example that exhibits the problem you envounter.
Addendum: Combining the methods is also possible:
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class JTabbedTest {
private static JTabbedPane jtp;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jtp = new JTabbedPane();
jtp.setPreferredSize(new Dimension(320, 200));
jtp.addTab("Reds", new ColorPanel(0, Color.RED));
jtp.setBackgroundAt(0, Color.RED);
jtp.addTab("Greens", new ColorPanel(1, Color.GREEN));
jtp.setBackgroundAt(1, Color.GREEN);
jtp.addTab("Blues", new ColorPanel(2, Color.BLUE));
jtp.setBackgroundAt(2, Color.BLUE);
f.add(jtp, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
});
}
private static class ColorPanel extends JPanel implements ActionListener {
private final Random rnd = new Random();
private final Timer timer = new Timer(1000, this);
private Color color;
private Color original;
private int mask;
private JLabel label = new JLabel("Stackoverflow!");
private int index;
public ColorPanel(int index, Color color) {
super(true);
this.color = color;
this.original = color;
this.mask = color.getRGB();
this.index = index;
this.setBackground(color);
label.setForeground(color);
this.add(label);
timer.start();
}
#Override
public void actionPerformed(ActionEvent e) {
color = new Color(rnd.nextInt() & mask);
this.setBackground(color);
jtp.setBackgroundAt(index, original);
}
}
}
most of method for JTabbedPane is protected in the API, and not accesible from Swing methods
have to look for Custom XxxTabbedPaneUI, override these methods, and could be accesible from outside
correct way would be to implement Custom Look & Feel only, part of them override JTabbedPane
example for Custom XxxTabbedPaneUI
You should consider using a Look and Feel that does what you want, or failing that, changing the default UIManger settings for a JTabbedPane:
UIManager.put("TabbedPane.background", Color.GRAY);
If you opt for the latter, it must be done before you create your GUI.
For more on this, please see Rob Camick's excellent blog on the subject: UIManager Defaults.
Edit: I was wrong. It should be:
UIManager.put("TabbedPane.unselectedBackground", Color.GRAY);
But note that this may not work with every Look and Feel.
It may be a problem that there is nothing added yet to the tab.
Try setting the content manager of the content panel to BorderLayout, adding a JPanel with BorderLayout. Center and then coloring that panel.