java JTabbedPane 自定义选项卡外观
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7859035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JTabbedPane customize tab look
提问by AgostinoX
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.
我想自定义 JTabbedPane 中选项卡的外观。
我想从最简单最朴素的行为开始:无边框,纯色。
问题是仍然存在一个不平的地方:标签页边距略有重叠。
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);
}
}
}
}
采纳答案by mKorbel
回答by AgostinoX
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:
第一个(部分)解决方案。我已经找到了“定位”代码。
这是该方法calculateTabRects
中TabbedPaneLayout
,一个内部类BasicTabbedPaneUI的。该方法极其复杂,但好消息是“在前面提出”选项卡的部分在其自己的可覆盖方法中得到了很好的注释和绝缘!它是padSelectedTab
。
创建一个什么都不做而不是提升组件的类就像这样简单:
protected class MyTabbedPaneLayout extends TabbedPaneLayout { @Override protected void padSelectedTab(int tabPlacement, int selectedIndex) { //do nothing! //super.padSelectedTab(tabPlacement, selectedIndex); } }
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:
请注意,它必须是 MyTabbedPane 的内部类。它必须通过覆盖 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 privateand not protected access, so it is not possible subclass it!
My createLayoutManager implmentation looses scrollable behavior.
非常简单且实际工作......除了一个案例。如果 tabLayoutPolicy 是 WRAP_TAB_LAYOUT,则 createLayoutManager 实例化 TabbedPaneLayout,但如果 tabLayoutPolicy 是 SCROLL_TAB_LAYOUT,则实例化 TabbedPanelScrollLayout。后者具有私有且不受保护的访问权限,因此不可能将其子类化!
我的 createLayoutManager 实现失去了可滚动行为。
回答by Mike Lowry
You can put Html tags into the first parameter as following :
您可以将 Html 标签放入第一个参数中,如下所示:
MyJTabbedPane.addTab("<html><h1 style='padding:20px;'>TEST</h1></html>", new JPanel());
MyJTabbedPane.addTab("<html><h1 style='padding:20px;'>TEST</h1></html>", new JPanel());
回答by kylewm
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 :)
您可以在 MyTabbedPaneUI 中覆盖 paintContentBorderTopEdge,这样它就不会认为任何选项卡被选中。这不是一个很好的解决方案,但根据我的经验,黑客 UI 类很少适用于:)
@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);
}