views:

477

answers:

3

I have been going nuts trying to figure this out.

I am trying to elimenate a light blue background that appears in a JTabbedPane. I've tried everything and nothing seems to work.

Below is my code. If you run it, it will show the tab, when selected with a light blue background and a thing blue border at the top. I want to control this color. But how?

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.ColorUIResource;
public class Main extends JFrame {
  JTabbedPane tab=new JTabbedPane();
  public Main() {
     setSize(300,300);
     setTitle("Test Tab pane");
     tab.add("First",new myPanel("First"));
     tab.add("Second",new myPanel("Second"));
     tab.add("Third",new myPanel("Third"));
     tab.add("Fourth",new myPanel("Fourth"));
     tab.addChangeListener(new ChangeTab());
     getContentPane().add(tab,BorderLayout.CENTER);
     setVisible(true);
     for(int i=0;i<tab.getTabCount();i++){
          if(i != tab.getSelectedIndex())
            tab.setBackgroundAt(i,Color.orange);
            tab.setForeground(Color.BLACK);
     }
     tab.setOpaque(true);
     UIManager.put("TabbedPane.contentAreaColor ",ColorUIResource.GREEN);
     UIManager.put("TabbedPane.selected",ColorUIResource.GREEN);
     UIManager.put("TabbedPane.background",ColorUIResource.GREEN);
     UIManager.put("TabbedPane.shadow",ColorUIResource.GREEN);
  }

  public static void main(String[] args) {
    Main main = new Main();
  }

  class ChangeTab implements ChangeListener{
    public void stateChanged(ChangeEvent e){
        tab.validate();
        System.out.println(tab.getSelectedIndex());
        for(int i=0;i<tab.getTabCount();i++){
          if(i != tab.getSelectedIndex())
            tab.setBackgroundAt(i,Color.orange);
        }

    }
  }

  class myPanel extends JPanel{
    public myPanel(String str){
       add(new JLabel(str));
    }
  }

}
A: 

Attempt 2: I fixed my border problem and changed look and feel manager. This still is not exactly what you are looking for though..

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.event.*; 
import javax.swing.plaf.ColorUIResource; 
public class Main extends JFrame { 
  JTabbedPane tab=new JTabbedPane(); 
  public Main() { 

     setBackground(Color.white);
     setSize(300,300); 
     setTitle("Test Tab pane"); 
     tab.add("First",new myPanel("First")); 
     tab.add("Second",new myPanel("Second")); 
     tab.add("Third",new myPanel("Third")); 
     tab.add("Fourth",new myPanel("Fourth")); 
     tab.addChangeListener(new ChangeTab()); 
     tab.setBackground(Color.white);
     tab.setForeground(Color.black);
     tab.setBorder(BorderFactory.createEmptyBorder());


     getContentPane().add(tab,BorderLayout.CENTER); 
     setVisible(true); 

  } 

  public static void main (String[] args) throws Exception { 
                           UIManager.setLookAndFeel(
            UIManager.getSystemLookAndFeelClassName());
    Main main = new Main(); 
  } 

  class ChangeTab implements ChangeListener{ 
    public void stateChanged(ChangeEvent e){ 
        tab.validate(); 
        System.out.println(tab.getSelectedIndex()); 

    } 
  } 

  class myPanel extends JPanel{ 
    public myPanel(String str){ 
       setBackground(Color.white); 
       setBorder(BorderFactory.createEmptyBorder());
       add(new JLabel(str)); 
    } 
  } 

} 
AJ
`setBorder()` takes a javax.swing.border.Border, not a Color object. Is the colour taken from the Border object instead?
Grundlefleck
Somebody posted the answer but now it is gone. Why? bug in Stackoverflow? The anwwer is to set parameters in the UIManager first then create the object. Do it in reverse and the code doesn't work.
Elliott
@Elliot: I deleted it myself because it doesn't solve your problem, only part of it. I'm still seeing the blue-ish grey border around the inner panel. Even using this answer as well.
Grundlefleck
You are right. I am seeing it too.
Elliott
Not sure how this helps. If you set the backgroun to Green under the myPanel method, you still have the problem.
Elliott
+2  A: 

I used your example code, and what worked for me was moving the calls to UIManager.put() to a point where they would be executed before the JTabbedPane constructor was executed.

public class Main extends JFrame {
    JTabbedPane tab;

    public Main() {
       // ... other stuff
       UIManager.put("TabbedPane.contentAreaColor ",ColorUIResource.GREEN);
       UIManager.put("TabbedPane.selected",ColorUIResource.GREEN);
       UIManager.put("TabbedPane.background",ColorUIResource.GREEN);
       UIManager.put("TabbedPane.shadow",ColorUIResource.GREEN);

       // now construct the tabbed pane
       tab=new JTabbedPane();

       // ... other stuff
 }

There's also some other properties available (for the Metal L&F, at least):

UIManager.put("TabbedPane.borderColor", Color.RED);
UIManager.put("TabbedPane.darkShadow", ColorUIResource.RED);
UIManager.put("TabbedPane.light", ColorUIResource.RED);
UIManager.put("TabbedPane.highlight", ColorUIResource.RED);
UIManager.put("TabbedPane.focus", ColorUIResource.RED);
UIManager.put("TabbedPane.unselectedBackground", ColorUIResource.RED);
UIManager.put("TabbedPane.selectHighlight", ColorUIResource.RED);
UIManager.put("TabbedPane.tabAreaBackground", ColorUIResource.RED);
UIManager.put("TabbedPane.borderHightlightColor", ColorUIResource.RED);

These let you control most of the colours in the tab area.

I found with these settings there was still a very small blue-ish grey border around the content. I have searched for how to set this colour to no avail. The only solution I could find to get rid of this was:

UIManager.put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0));

Which is a sub-optimal solution.

Grundlefleck
Actually, this works for me. Why do you call it suboptimal?
Elliott
Because, and I'm not sure about this, it will make the content of the tab sit right up against the edges. E.g. if you have a component in there, such as a button in the North area, the top of the button will touch the top of the tab, which is probably not what you want when you would rather just control the colour.
Grundlefleck
Yeah. I thought about that, but was able to address it by putting a border around the content area of the container accessed by the TabbedPane. The border that is not a property of the JTabbedPane itself but of the container. That Border is completely controlable by me and thus solves the problem (though admittedly, not the most elegant solution). But then again, neither is the implmentation of this Swing control.
Elliott
A: 

Check the results with these values.

UIManager.put("TabbedPane.contentAreaColor", Color.GREEN);
UIManager.put("TabbedPane.light", ColorUIResource.GREEN);
UIManager.put("TabbedPane.highlight", ColorUIResource.GREEN);
UIManager.put("TabbedPane.shadow", ColorUIResource.GREEN);
UIManager.put("TabbedPane.darkShadow", ColorUIResource.GREEN);
UIManager.put("TabbedPane.selected", ColorUIResource.GREEN);
UIManager.put("TabbedPane.borderHightlightColor", ColorUIResource.GREEN);

As you can see, the only way, to get the dark border on top of the panel the color you want is to set "borderHightlightColor" to the desired Color. Unfortunately, this has the side effects that can be seen (green border around all tabs). And still, there is this gray line between the green ones that comes from the background.

I think the only real solution to this is to override your MetalTabbedPaneUI. If you only set contentAreaColor and do empty overrides for the methods

paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h);
paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h); 
paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h);
paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h); 

the result should be near the one I suspect you want to get.

Mathias Weyel