JTabbedPane:如何从上到下订购标签,而不是从下到上?

时间:2018-05-01 01:13:47

标签: java swing jtabbedpane

JTabbedPane中,标签的顺序是从下到上: enter image description here

我希望它从上到下,这意味着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,这感觉就像一个黑客。

有没有办法在没有毛刺的情况下做到这一点?我想我必须覆盖BasicTabbedPaneUI中的某些方法,但我无法找到哪一种。

1 个答案:

答案 0 :(得分:1)

我终于找到了解决方案。

正如@Joe Coder所说,你必须覆盖calculateTabRects()方法。但是,此方法属于内部类。没有办法扩展BasicTabbedPaneUI或内部类,因为有太多的受保护和私有字段。解决方案是通过复制粘贴所有代码来重新创建相关的类。

源代码来自here

相关修改在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的代码,您会发现还需要复制粘贴LazyActionMapBasicGraphicsUtils

为方便起见,以下是复制粘贴所需的所有代码。确保不要覆盖包,如果它不在包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地狱在这里完成,但在当前状态下,“运行”(标签行)之间的线条消失了: enter image description here

解决方案是在选择具有UIManager.setLookAndFeel()的用户界面后添加以下内容:

    UIManager.getDefaults().put("TabbedPane.tabRunOverlay", 0);
    UIManager.getDefaults().put("TabbedPane.focus", new Color(0, 0, 0, 0));

结果:

enter image description here