JTabbedPane: Как упорядочить вкладки сверху вниз, а не снизу вверх? - PullRequest
0 голосов
/ 01 мая 2018

В 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 голосов
/ 01 мая 2018

Я наконец нашел решение.

Как сказал @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

Здесь заканчивается ООП-ад, но в текущем состоянии строки между «прогонами» (строки табуляции) исчезают 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

...