JTabbedPane:如果堆叠/Nimbus,避免自动重新排序选项卡

发布于 2024-12-05 08:43:48 字数 450 浏览 0 评论 0 原文

JTabbedPane 正是我所需要的。 我的水平空间非常有限,所以我的选项卡会堆叠起来,这完全没问题。

但默认行为是,如果用户单击某个选项卡,选项卡就会重新排序,以便活动选项卡成为最下方的选项卡。*t。理论上看起来非常直观和合乎逻辑的东西,在实际使用中却是一场噩梦,因为用户无法区分“哪个是哪个”。人们一次又一次地告诉我,这简直令人困惑。

我想应该可以重写 UI 的某些方法来避免这种行为(而且我不关心纸卡在物理上是否可行:-)。

有人知道我需要在哪里这样做吗?我正在使用 Nimbus LAF,这似乎并没有让它变得更容易。

(我考虑过使用 radiobuttons/cardLayout,但我需要在选项卡标题中放置一个自定义面板,而 radiobuttons 只能有一个字符串或图标。JToggleButton 也是如此...)

非常欢迎任何提示!

谢谢&亲切的问候, 菲利普

a JTabbedPane is just what I need for my purpose.
I have very limited horizontal space, so my Tabs get stacked, which is perfectly ok.

But the default behaviour is that if user clicks on a Tab, the *Tabs get re-sorted so that the active Tab becomes the lower-mos*t. What looks very intuitive and logical in theory, is a nightmare in practical use, because the users loose track of "which was which". Its just simply plain confusing, I am told again and again.

I guess it should be possible to override some method of the UI to avoid this behaviour (and I dont care whether this would be physically possible with paper cards :-) .

Has anyone any idea where I need to do that? I am using Nimbus LAF, which does not seem to make it easier.

(I thought about using radiobuttons/cardLayout, but I need to put a custom panel in the tab title, and radiobuttons can only have a string or icon. Same for JToggleButton...)

Any hints are greatly welcome!

Thanks & Kind regards,
Philipp

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

寄居人 2024-12-12 08:43:48

sscce 用于 Nimbus L&f 的潜在回答者(通过使用另一个 L&f 不可能重现这个有趣的问题),如果 Containers#Size 将 Tab 打包到两个或更多 Lines
在此处输入图像描述在此处输入图片描述

据我所知,只有一个可能的解决方案(不覆盖 NimbusTabbedPaneUI),作者:aephyr

来自 sscce

import java.awt.BorderLayout;
import javax.swing.*;

public class TabbedPane {

    private static final long serialVersionUID = 1L;

    public TabbedPane() {
        JPanel jp = new JPanel();
        jp.setLayout(new BorderLayout());
        JTabbedPane tb = new JTabbedPane();
        //tb.setUI(new CustomTabbedPaneUI());
        tb.add("Tab1", new JTextArea(10, 20));
        tb.add("Tab2", new JTextArea(10, 20));
        tb.add("Tab3", new JTextArea(10, 20));
        tb.add("Tab4", new JTextArea(10, 20));
        tb.add("Tab5", new JTextArea(10, 20));
        jp.add(tb, BorderLayout.CENTER);
        //add(jp, BorderLayout.CENTER);
        //tb.setEnabledAt(1, false);
        //tb.setEnabledAt(3, false);
        JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());
        frame.add(jp, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception system) {
            system.printStackTrace();
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                TabbedPane tP = new TabbedPane();
            }
        });
    }
}

sscce for potential answerer(s) for Nimbus L&f (by using another L&f isn't possible to reproduce this funny issue), in case that Containers#Size packed Tabs to the two or more Lines,
enter image description hereenter image description here

as I know there is only one possible solutions (without override NimbusTabbedPaneUI) by aephyr

from sscce

import java.awt.BorderLayout;
import javax.swing.*;

public class TabbedPane {

    private static final long serialVersionUID = 1L;

    public TabbedPane() {
        JPanel jp = new JPanel();
        jp.setLayout(new BorderLayout());
        JTabbedPane tb = new JTabbedPane();
        //tb.setUI(new CustomTabbedPaneUI());
        tb.add("Tab1", new JTextArea(10, 20));
        tb.add("Tab2", new JTextArea(10, 20));
        tb.add("Tab3", new JTextArea(10, 20));
        tb.add("Tab4", new JTextArea(10, 20));
        tb.add("Tab5", new JTextArea(10, 20));
        jp.add(tb, BorderLayout.CENTER);
        //add(jp, BorderLayout.CENTER);
        //tb.setEnabledAt(1, false);
        //tb.setEnabledAt(3, false);
        JFrame frame = new JFrame();
        frame.setLayout(new BorderLayout());
        frame.add(jp, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        try {
            for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (Exception system) {
            system.printStackTrace();
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                TabbedPane tP = new TabbedPane();
            }
        });
    }
}
梦旅人picnic 2024-12-12 08:43:48

好的,我发现了问题。里面

package javax.swing.plaf.basic.BasicTabbedPaneUI;

说了这样的话

// Rotate run array so that selected run is first
            if (shouldRotateTabRuns(tabPlacement)) {
                rotateTabRuns(tabPlacement, selectedRun);
            }

遗憾的是,似乎没有简单的“设置一个标志,然后你就可以走”的方法来改变这一点。

虽然如果您省略了对 rotateTabRuns(tabPlacement, selectedRun); 的调用或更改 shouldRotateTabRuns(tabPlacement) 的话应该没问题......但是,这样做您必须重写一大堆类...取决于您使用的平台。

它像这样继承

Basic > Synth > Nimbus

并且在每个L&F级别上都有几个类可以自定义......我没有数过。

希望有帮助! :D

编辑
哦,是的...@mkorbel 已经提供了这个 aephyr 的解决方案,为什么不使用它呢?

Okay, I found the Problem. In

package javax.swing.plaf.basic.BasicTabbedPaneUI;

it says something like this

// Rotate run array so that selected run is first
            if (shouldRotateTabRuns(tabPlacement)) {
                rotateTabRuns(tabPlacement, selectedRun);
            }

Its a pity that there seems to be no easy set-a-flag-and-there-you-go-way is for changing that.

Although you should be fine if you omitted the call to rotateTabRuns(tabPlacement, selectedRun); or change shouldRotateTabRuns(tabPlacement) for that matter... however, to do so you would have to override a whole bunch of classes... depending on which plaf you use.

It inherits like this

Basic > Synth > Nimbus

And on each L&F-level there are several classes to customize... I didn't count.

Hope it helps! :D

Edit
Oh yeah... @mkorbel already provided sort of the solution with this aephyr why not use that?

守望孤独 2024-12-12 08:43:48

这有点麻烦,但您可以覆盖 Nimbus 默认值,使选项卡式窗格具有普通的旧 Java 外观和感觉,同时保持其他所有内容相同。选项卡式窗格的普通 Java 外观不会进行烦人的重新排序。只需在设置外观之前存储默认值,然后将其设置回来即可。

// get the defaults to keep
HashMap<Object, Object> defaultsToKeep = new HashMap<>();
for (Map.Entry<Object, Object> entry : UIManager.getDefaults().entrySet()) {
    boolean isStringKey = entry.getKey().getClass() == String.class ;
    String key = isStringKey ? ((String) entry.getKey()):"";    
    if (key.startsWith("TabbedPane")) {
        defaultsToKeep.put(entry.getKey(), entry.getValue());
    }
}

// set nimbus look and feel
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
    if ("Nimbus".equals(info.getName())) {
        UIManager.setLookAndFeel(info.getClassName());
        break;
    }
}

// set back your originals
for (Map.Entry<Object, Object> entry : defaultsToKeep.entrySet()) {
    UIManager.getDefaults().put(entry.getKey(), entry.getValue());
}

JFrame.setDefaultLookAndFeelDecorated(true);

It's a bit of a hack but you can override the Nimbus defaults to have the plain old Java look-and-feel for the tabbed pane, whilst keeping everything else the same. The plain Java look-and-feel for a tabbed pane doesn't do the annoying reordering. Just store the defaults before you set the look-and-feel and then set them back.

// get the defaults to keep
HashMap<Object, Object> defaultsToKeep = new HashMap<>();
for (Map.Entry<Object, Object> entry : UIManager.getDefaults().entrySet()) {
    boolean isStringKey = entry.getKey().getClass() == String.class ;
    String key = isStringKey ? ((String) entry.getKey()):"";    
    if (key.startsWith("TabbedPane")) {
        defaultsToKeep.put(entry.getKey(), entry.getValue());
    }
}

// set nimbus look and feel
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
    if ("Nimbus".equals(info.getName())) {
        UIManager.setLookAndFeel(info.getClassName());
        break;
    }
}

// set back your originals
for (Map.Entry<Object, Object> entry : defaultsToKeep.entrySet()) {
    UIManager.getDefaults().put(entry.getKey(), entry.getValue());
}

JFrame.setDefaultLookAndFeelDecorated(true);
哎呦我呸! 2024-12-12 08:43:48

最初的问题是针对 Nimbus 的,但我在 FlatLaf 中遇到了同样的问题。
我通过在应用程序初始化期间设置此选项解决了这个问题:

UIManager.getDefaults().put("TabbedPane.rotateTabRuns", false);

The original question was for Nimbus but I ran into the same issue with FlatLaf.
I got around the problem by setting this option during the application initialization:

UIManager.getDefaults().put("TabbedPane.rotateTabRuns", false);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文