JTabbedPane tab component resize to fit

人走茶凉 提交于 2019-12-21 22:04:08

问题


I want to make my tab labels share the JTabbedPane width. If there's one tab, fit whole width, if two tabs, share width, if three, 1/3 for each and so on...

i don't even know if it's possible to do it without putting a component there and resizing it, maybe JTabbedPane has a way of resizing it's tab label via method and i don't know...

Anyone got any idea how to make it by the easiest way possible?


回答1:


As @trashgod already noted, the tab layout is handled by the LAF-specific SomeLAFTabbedPaneUI, more specifically the TabbedPaneLayout. So the way to go is

  • implement a custom subclass MySomeLAFTabbedPaneUI which has a custom extended TabbedPaneLayout (you need to do that for every SomeLAF you want to support
  • replace the normal ui by your custom class

The first boils down to hook into the calculation of the rectangles which are used for painting the tabs/locating custom tabComponents. Something like (note: obviously not production ready :-)

public class XMetalTabbedPaneUI extends MetalTabbedPaneUI {

    public static ComponentUI createUI(JComponent c) {
        return new XMetalTabbedPaneUI();
    }

    @Override
    protected LayoutManager createLayoutManager() {
        return new XTabbedPaneLayout();
    }


    protected class XTabbedPaneLayout extends MetalTabbedPaneUI.TabbedPaneLayout {

        protected Container tabContainer;

        @Override
        protected void calculateTabRects(int tabPlacement, int tabCount) {
            super.calculateTabRects(tabPlacement, tabCount);
            // TODO: check if it makes sense to stretch
            int max = 0;
            int sum = 0;
            Rectangle r = new Rectangle();
            for (int i = 0; i < tabCount; i++) {
                getTabBounds(i, r);
                max = Math.max(max, r.width);
                sum += r.width;
            }
            // TODO: calculate real width, that is -insets
            int paneWidth = tabPane.getWidth() - 10; 
            int free = paneWidth - sum;
            // nothing to distribute
            if (free < tabCount) return;
            int add = free /tabCount;
            int offset = 0;
            for (int i = 0; i < tabCount; i++) {
                r = rects[i]; 
                r.x += offset;
                r.width += add;
                offset += add;
            }

        }

    }
}

The second is highly simplified (biased me, as the maintainer of the project :-) by the plaf enhancement mechanism provided by SwingX (actually all you need is its plaf module and dependencies). Its basic building block is a TabbedPaneAddon which loads the custom ui:

public class TabbedPaneAddon extends AbstractComponentAddon {

    /**
     * @param name
     */
    public TabbedPaneAddon() {
        super("TabbedPane");
    }

    @Override
    protected void addMetalDefaults(LookAndFeelAddons addon,
            DefaultsList defaults) {
        // remove old ui
        UIManager.getLookAndFeelDefaults().put("TabbedPaneUI", null);
        defaults.add("TabbedPaneUI",
                // here goes the full classname of your custom ui
                // this is an example only :-)
                "org.jdesktop.swingx.XMetalTabbedPaneUI");
    }

    // implement other addXXDefault as needed for 
    // supporting more LAFs
}

The make the replacement happen, you have to contribute the addon ("early") in your application:

LookAndFeelAddons.contribute(new TabbedPaneAddon()); 



回答2:


Is there a Look & Feel that has this "tab fitting" capability?

I don't know of one, but you might post an illustration for others who may have seen something similar. As the appearance is controlled by the L&F's UI delegate, TabbedPaneUI, you need to either look for an existing implementation or subclass one of its descendants: BasicTabbedPaneUI or MetalTabbedPaneUI.



来源:https://stackoverflow.com/questions/17754098/jtabbedpane-tab-component-resize-to-fit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!