在
JTabbedPane
中,选项卡的顺序是从下到上:
我希望它是从上到下,这意味着 tab0 将在顶行,而 tab60 将在底行。
代码:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;
public class Class1 {
public static JTabbedPane jtp;
public static void main(String[] args) {
JFrame window = new JFrame();
window.setTitle("Parent frame");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(600, 400);
window.setLocationRelativeTo(null);
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
jtp = new JTabbedPane();
window.add(jtp);
/*WindowsTabbedPaneUI btpui = new WindowsTabbedPaneUI() {
@Override protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) {
int tabCount = tabPane.getTabCount();
Rectangle iconRect = new Rectangle(),
textRect = new Rectangle();
Rectangle clipRect = g.getClipBounds();
// Paint tabRuns of tabs from front to back
for (int i = 0; i < runCount; i++) {
int start = tabRuns[i];
int next = tabRuns[(i == runCount - 1)? 0 : i + 1];
int end = (next != 0? next - 1: tabCount - 1);
for (int j = start; j <= end; j++) {
if (j != selectedIndex && rects[j].intersects(clipRect)) {
paintTab(g, tabPlacement, rects, j, iconRect, textRect);
}
}
}
// Paint selected tab if its in the front run
// since it may overlap other tabs
if (selectedIndex >= 0 && rects[selectedIndex].intersects(clipRect)) {
paintTab(g, tabPlacement, rects, selectedIndex, iconRect, textRect);
}
}
};
jtp.setUI(btpui);*/
//jtp.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
for (int i = 0; i <= 60; i++) {
jtp.addTab("tab"+i, new JPanel());
}
window.setVisible(true);
}
}
我试过覆盖
paintTabArea()
中的WindowsTabbedPaneUI
方法从上到下绘画,但它似乎没有做任何事情。
我找到了 2 个解决方法:
将标签放在底部,以便它们以正确的方式对齐(但我想将它们放在顶部)
以相反的顺序排列选项卡,然后将组件从右到左对齐。然而,这会产生视觉故障:左侧的选项卡太靠近边框,左侧的选项卡与其他选项卡之间有空间,右侧的选项卡在边框上形成凹痕。我还必须重写
addTab()
方法,并在只有一行时放入 LTR,这感觉像是 hack。
有没有办法做到这一点而不会出现故障?我想我必须重写
BasicTabbedPaneUI
的一些方法,但我找不到哪个。
我终于找到了解决方案
正如@Joe Coder 所说,您必须重写
calculateTabRects()
方法。但是,此方法位于内部类中。没有办法扩展 BasicTabbedPaneUI
或内部类,因为有太多的受保护和私有字段。解决方案是通过复制粘贴所有代码来重新创建相关类。
源码来自这里.
相关修改在
calculateTabRects()
方法中,更具体地说是在那个for循环中:
// Step through runs from back to front to calculate
// tab y locations and to pad runs appropriately
for (i = runCount - 1; i >= 0; i--) {
//...
}
简单地反向迭代就可以了:
for (i = 0; i < runCount; i++) {...}
现在,如果你复制粘贴
BasicTabbedPaneUI
的代码,你会发现你还需要复制粘贴LazyActionMap
和BasicGraphicsUtils
。
为方便起见,这里是您需要复制粘贴的所有代码。确保不要覆盖包,如果它不在包中
javax.swing.plaf.basic
它将无法工作。
FixedTabbedPaneUI.java:https://pastebin.com/W8RBD4vg
LazyActionMap2.java:https://pastebin.com/RKtDgJB5
BasicGraphicsUtils2.java:https://pastebin.com/Au4hcSyp
但是,就我而言,我需要一个
WindowsTabbedPaneUI
。所以这是 WindowsTabbedPaneUI2.java:https://pastebin.com/89UedgbQ
..XPStyle2.java:https://pastebin.com/xCsm8DZc
..和AnimationController2.java:https://pastebin.com/7Pm0s5eG
OOP 地狱到此结束,但在当前状态下,“运行”(制表符行)之间的线消失了:
解决方案是在选择带有
UIManager.setLookAndFeel()
的UI后放入以下内容:
UIManager.getDefaults().put("TabbedPane.tabRunOverlay", 0);
UIManager.getDefaults().put("TabbedPane.focus", new Color(0, 0, 0, 0));
结果:
您可以通过扩展
BasicTabbedPaneUI
和覆盖 createLayoutManager
来更容易地实现它,并在那里返回 TabbedPaneLayout
覆盖必要的方法。