JTabbedPane 正是我达到目的所需要的。 我的水平空间非常有限,所以我的选项卡会堆叠起来,这完全没问题。
但默认行为是,如果用户单击某个选项卡,*选项卡将重新排序,以便活动选项卡成为最下方的*t。理论上看起来非常直观和合乎逻辑的东西,在实际使用中却是一场噩梦,因为用户无法区分“哪个是哪个”。人们一遍又一遍地告诉我,这简直令人困惑。
我想应该可以重写 UI 的某些方法来避免这种行为(而且我不关心这对于纸卡来说是否可行:-)。
有人知道我需要在哪里这样做吗?我正在使用 Nimbus LAF,这似乎并没有使它变得更容易。
(我想过使用radiobuttons/cardLayout,但我需要在选项卡标题中放置一个自定义面板,而radiobuttons只能有一个字符串或图标。JToggleButton也是如此...)
非常欢迎任何提示!
感谢和亲切的问候, 菲利普
sscce 对于 Nimbus L&f 的潜在回答者(通过使用另一个 L&f 不可能重现这个有趣的问题),以防 Containers#Size 将选项卡压缩到两个或更多
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();
}
});
}
}
好的,我找到问题了。在
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)
的话应该没问题......但是,要做到这一点,你将必须重写一大堆类......取决于你使用哪个 plaf 。
就这样继承了
Basic > Synth > Nimbus
并且在每个 L&F 级别上都有几个可以自定义的课程...我没有数过。
希望有帮助! :D
编辑 哦,是的...@mkorbel 已经提供了一些解决方案,aephyr 为什么不使用它?
这有点麻烦,但您可以覆盖 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);
最初的问题是针对 Nimbus 的,但我在 FlatLaf 上遇到了同样的问题。 我通过在应用程序初始化期间设置此选项解决了这个问题:
UIManager.getDefaults().put("TabbedPane.rotateTabRuns", false);