1

I want to create a JTabbedPane using the Nimbus Look and Feel that has different colors for each tab. I have found multiple ways to change the colors, but as far as I can tell, these technique apply globally to all tabs with a certain state (such as changing all tabs with TabbedPane:TabbedPaneTab[Enabled].backgroundPainter to be the same color)

Two useful SO links I have found (close but not quite the answer to my question):

Override Swing Nimbus L&F primary color per component instance

Set the Background Color for JTabbedPane

Below is a mockup image of what I'd like to achieve.

enter image description here

*edit - sorry forgot to include demo program source code. (This doesn't create the coloring but otherwise launches a new window with the appropriate tab pane.):

public class TabbedPaneExample extends JFrame {
    public static void main(String args[]) {
        try {
            for(javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.
                    getInstalledLookAndFeels()) {
                if("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        }
        catch(Exception ex) {
            ex.printStackTrace();
        }

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TabbedPaneExample().setVisible(true);
            }
        });
    }

    public TabbedPaneExample(){
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        JTabbedPane pane = new JTabbedPane();
        pane.addTab("Blue", new JLabel("Blue tab"));
        pane.addTab("Red", new JLabel("Red tab"));
        pane.addTab("Yellow", new JLabel("Yellow tab"));

        this.add(pane);

        pack();
    }
}

*Edit - In regards to zilk's answer below - it does not appear to work. Extending BasicTabbedPaneUI causes the Nimbus specific rendering to be lost. In order to keep the Nimbus rendering, SynthTabbedPaneUI needs to be extended. However, SynthTabbedPaneUI doesn't call paintTabBackground, instead it calls paintTabArea, which is both a protected method and an overloaded private helper method. It looks like all the logic occurs in the private helper method. I can't reproduce that private method in my own code because of private instance variables in SynthTabbedPaneUI and package private code in SynthContext which is used by paintTabArea.

Community
  • 1
  • 1
Gregory Peck
  • 636
  • 7
  • 22

1 Answers1

0

You can set new UI that is extended BasicTabbedPaneUI for your tabbedpane. After that you should just override the paintTabBackground method. Try this codes

pane.setUI(new BasicTabbedPaneUI(){
        @Override
        protected void paintTabBackground(Graphics g, int tabPlacement,int tabIndex, int x, int y, int w, int h, boolean isSelected){
           //default backcolor 
           Color bg = Color.LIGHT_GRAY;

           switch(tabIndex){
             case 0:
                   bg = Color.BLUE;  
                   break;   
              case 1: 
                   bg = Color.YELLOW;
                   break;
              case 2: 
                   bg = Color.RED;
                   break;
               }
            g.setColor(bg);

           switch (tabPlacement){
              case SwingConstants.TOP:
                   g.fillRect(x + 1, y + 1, w - 1, h - 1);
                   break;
              case SwingConstants.BOTTOM:
                   g.fillRect(x, y, w - 1, h - 1);
                   break;
              case SwingConstants.LEFT:
                   g.fillRect(x + 1, y + 1, w - 1, h - 2);
                   break;
              case SwingConstants.RIGHT:
                   g.fillRect(x, y + 1, w - 1, h - 2);
                   break;
               }
    }
 });

Edit: Here is my codes result enter image description here

P.S: Do not forget this

pane.setOpaque(true);
ziLk
  • 3,120
  • 21
  • 45
  • This appears to not work for Nimbus only. Extending `BasicTabbedPaneUI` causes the Nimbus specific rendering to be lost. In order to keep the Nimbus rendering, `SynthTabbedPaneUI` needs to be extended. However, `SynthTabbedPaneUI` doesn't call `paintTabBackground`, instead it calls `paintTabArea`, which is a protected method and a private helper method. It looks like all the logic occurs in the private method, and I can't reproduce that because of private instance variables. I'll update my answer w/ more information. – Gregory Peck Mar 28 '16 at 13:33
  • I don't understand why you need this for only Nimbus. And what do you actually mean about "loosing/keeping Nimbus rendering " ? My codes work properly as your mockup – ziLk Mar 29 '16 at 10:50
  • Our applications use the Nimbus L&F. When extending `BasicTabbedPaneUI`, the `JTabbedPane` takes on the appearance of the Metal L&F (and it no longer has the Nimbus L&F). This makes the `JTabbedPane` look out of place in our application. Here is an image that demonstrates the normal Nimbus `JTabbedPane` side by side with the custom `JTabbedPane` using `BasicTabbedPaneUI`. http://i.imgur.com/Lv2lmHK.png Note how the appearance of the corners, borders, gradients, and selection highlight appear different. I can't figure out how to achieve the different tab colors and keep the Nimbus L&F. – Gregory Peck Mar 29 '16 at 17:19