JTabbedPane customize tab look
Asked Answered
C

4

9

I want to customize the look of the tabs in JTabbedPane.
I want to start from the simplest and plainest behavior: no borders, solid color.
The problem is that a non-plainess still remains: the tabs slight margin overlap.

enter image description here

You see that since the second tab is selected, it is "brought to the fore". This is achieved by a slight margin overlap. Is there a (non tricky) way to disable this behavior?

simple, testable (just fix imports) code:

public class TabbedPane_LookStudy extends JFrame{

public static void main(String [] args) throws UnsupportedLookAndFeelException {
    UIManager.setLookAndFeel(new NimbusLookAndFeel());
    new TabbedPane_LookStudy().setVisible(true);
}

public TabbedPane_LookStudy() {
    JTabbedPane tp = new JTabbedPane();
    tp.setUI(new MyTabbedPaneUI());
    add(tp);

    tp.addTab("first",new JPanel());
    tp.addTab("second", new JPanel());
    tp.addTab("third", new JPanel());

    setPreferredSize(new Dimension(180,100));
    pack();
}

public static class MyTabbedPaneUI extends javax.swing.plaf.basic.BasicTabbedPaneUI {

    @Override
    protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects, 
               int tabIndex, Rectangle iconRect, Rectangle textRect) {
        Color savedColor = g.getColor();
        g.setColor(Color.PINK);
        g.fillRect(rects[tabIndex].x, rects[tabIndex].y, 
               rects[tabIndex].width, rects[tabIndex].height);
        g.setColor(Color.BLUE);
        g.drawRect(rects[tabIndex].x, rects[tabIndex].y, 
               rects[tabIndex].width, rects[tabIndex].height);
        g.setColor(savedColor);
    }
 }

}

Candleberry answered 22/10, 2011 at 11:4 Comment(0)
T
4

Correct way would be to implement Custom Look & Feel only. But if you want to play with XxxTabbedPaneUI, then maybe this post can help you with that.

for Nimbus will be better to check aephyr code depot

Transitory answered 22/10, 2011 at 11:12 Comment(3)
i started from that post. But in that UI implementation, there are only paintXXX methods and calculateTabWidth and calculateTabHeight and NOT tab placement. So I tought that tab placement logic must be contained elsewhere.Candleberry
what's NOT tab placement you can paint that from the Top throught Border(s).... to the bottom, Tab Pacement is on the top ?Transitory
sorry, mKorbel, i don't get it. could you paraphrase?Candleberry
C
2

First (partial) solution. I've located the "positioning" code.
It is the method calculateTabRects in TabbedPaneLayout, an inner class of BasicTabbedPaneUI. The method is extremely complex, but the good new is that the part that "raises in front" the tab is well commented and insulated in its own overridable method! It is padSelectedTab.

Create a class that does nothing instead of raising the component is as simple as:

    protected class MyTabbedPaneLayout extends TabbedPaneLayout {
        @Override
        protected void padSelectedTab(int tabPlacement, int selectedIndex) {
            //do nothing!
            //super.padSelectedTab(tabPlacement, selectedIndex);
        }
    }

Notice that it has to be an inner class of MyTabbedPane. It has to be instantiated by overriding MyTabbedPane.createLayoutManager:

@Override
    protected LayoutManager createLayoutManager() {
        //return super.createLayoutManager();
         return new MyTabbedPaneLayout();
    }

Very easy and actually working... except for a case. The createLayoutManager instantiates TabbedPaneLayout if the tabLayoutPolicy is WRAP_TAB_LAYOUT, but instantiates TabbedPanelScrollLayout if tabLayoutPolicy is SCROLL_TAB_LAYOUT. The latter has private and not protected access, so it is not possible subclass it!
My createLayoutManager implmentation looses scrollable behavior.

Candleberry answered 22/10, 2011 at 16:3 Comment(0)
W
2

You can put Html tags into the first parameter as following :

MyJTabbedPane.addTab("<html><h1 style='padding:20px;'>TEST</h1></html>", new JPanel());

Winkle answered 24/3, 2014 at 15:47 Comment(0)
O
1

You can override paintContentBorderTopEdge in MyTabbedPaneUI so that it doesn't think any of the tabs are selected. This is not a pretty solution, but hacking UI classes rarely lends itself to one in my experience :)

@Override
protected void paintContentBorderTopEdge(Graphics g, int tabPlacement,
                       int selectedIndex, int x, int y, int w, int h) {
    super.paintContentBorderTopEdge(g, tabPlacement, -1, x, y, w, h);
}
Overalls answered 22/10, 2011 at 15:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.