问题
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