Java 空JTabbedPane

Java 空JTabbedPane,java,swing,jtabbedpane,Java,Swing,Jtabbedpane,我在创建一个空的JTabbedPane时遇到了一个问题,其中GUI上唯一可以看到的部分是一行选项卡 每次我添加带有“空”组件的新选项卡时,JTabbedPane的高度都会增加,但为什么 当前的解决方法是覆盖getPreferredSize(),但对我来说这似乎很麻烦。注释掉重写的方法以了解我的意思 我错过了什么明显的东西吗 背景: 我们需要一个JTabbedPane,其中选项卡式窗格以2个选项卡开始,但用户可以根据需要添加更多选项卡,最多10个。此外,每个选项卡包含相同的组件,但数据不同。决定

我在创建一个空的JTabbedPane时遇到了一个问题,其中GUI上唯一可以看到的部分是一行选项卡

每次我添加带有“空”组件的新选项卡时,JTabbedPane的高度都会增加,但为什么

当前的解决方法是覆盖
getPreferredSize()
,但对我来说这似乎很麻烦。注释掉重写的方法以了解我的意思

我错过了什么明显的东西吗


背景:

我们需要一个JTabbedPane,其中选项卡式窗格以2个选项卡开始,但用户可以根据需要添加更多选项卡,最多10个。此外,每个选项卡包含相同的组件,但数据不同。决定通过实现一个只用于外观的空JTabbedPane来伪造JTabbedPane的外观,并使用一个固定的JPanel,其内容将根据单击的选项卡刷新

(通常,我可以n次重新创建JPanel,但这对于控制UI的presenter类来说是噩梦,这超出了我的问题范围。)


import java.awt.*;
导入java.awt.event.*;
导入javax.swing.*;
公共类CustomTabbedPane实现可运行
{
静态final int MAX_TABS=11;//包括“添加”选项卡
JPanel pnlTabs;
JTabbedPane选项卡窗格;
公共静态void main(字符串[]args)
{
invokeLater(新的CustomTabbedPane());
}
公开募捐
{
JPanel p=buildPanel();
JFrame=新JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(p);
框架设置尺寸(800400);
frame.setVisible(true);
}
私有JPanel buildPanel()
{
tabbedPane=新的JTabbedPane()
{
@凌驾
公共维度getPreferredSize()
{
维度dim=super.getPreferredSize();
dim.height=getUI();
返回暗淡;
}
};
addTab(“tab1”,getEmptyComp());
addTab(“tab2”,getEmptyComp());
tabbedPane.addTab(“+”,新TabCreator());
tabbedPane.addMouseListener(新的MouseAdapter()
{
@凌驾
公共无效mouseClicked(MouseEvent e)
{
addTab();
}
});
JScrollPane scroll=新的JScrollPane(新的JTable(5,10));
JPanel p=newjpanel(newborderlayout());
p、 添加(选项卡窗格,BorderLayout.NORTH);
p、 添加(滚动、边框布局、居中);
p、 setBordOrder(BorderFactory.createLineBorder(Color.BLUE.darker(),1));
返回p;
}
私有void addTab()
{
if(tabbedPane.getSelectedComponent()实例为TabCreator)
{
int selIndex=tabbedPane.getSelectedIndex();
if(tabbedPane.getComponentCount()
好问题!但是,要想了解正在发生的事情是相当简单的

问题是您的内容没有最小宽度,未设置首选大小,选项卡位置为上/下,UI为默认值

由于未设置首选尺寸,因此当重新验证布局时,所需空间的计算进入
BasicTabbedPaneUI
方法
Dimension calculateSize(false)

内容如下:

int height = 0;
int width = 0;
<other vars>
// Determine minimum size required to display largest
// child in each dimension
<actual method>
这里发生的是,它将首选宽度设置为最大选项卡宽度和最大子宽度中的最大值。在你的例子中,标签文本大约是44。然后计算
tabExtent
,查看支持此首选宽度所需的选项卡行数。在您的情况下,每个选项卡都有一行额外的选项卡。这就是
preferredSize().height
中的额外高度的来源。基本上是因为对于水平选项卡放置,它首先关心宽度,然后是高度

如何修复:

  • 设置首选大小:)我知道很多人都说不要设置首选大小,但在这种情况下,这只会起作用。由于设置了首选大小(通过实际设置,而不是覆盖
    getPreferredSize()
    ),因此代码永远不会进入计数选项卡
  • 至少为您的一个孩子指定一个尺码(通过
    setPreferredSize
    或覆盖
    getPreferredSize
    )。如果其中一个子项的宽度是框架的宽度,或者说是底部的表格的宽度,则TabbedPane不会为每个选项卡分配额外的行,因为一行可以容纳所有内容
  • 为选项卡式窗格创建自己的UI。制作自己的选项卡式窗格可能更容易,但实际上,我从未这样做过
  • 编辑:


    仔细考虑后,我意识到解决方案1和您自己的解决方案存在一个缺陷,即如果选项卡式窗格确实需要多行选项卡(hello frame resizes),则会发生不好的事情。不要使用它。

    +1好信息。到目前为止(在阅读了您的编辑之后),我对OP中的解决方案没有任何问题,可能是因为我只有一小部分可以创建的固定数量的选项卡。下周我会更深入地研究它。谢谢。@splungebob我遇到了一个问题,我打开了6个标签,然后把窗口弄得足够小,这样标签就不能水平放置。然后它只显示最后3个tabs@splungebob我确信这里有几次“如何在不使用JTabbedPane的情况下模拟/绘制JTabbedPane”,或者在Coreranch(由Walter Laan、Michael Dunn、aterai撰写)@Ordous+1讨论一个问题,不同意BasicsTabbedPaneUI中的setXxxSize,可能是平台和L&F敏感的,可以
    int height = 0;
    int width = 0;
    <other vars>
    // Determine minimum size required to display largest
    // child in each dimension
    <actual method>
    
    switch(tabPlacement) {
        case LEFT:
        case RIGHT:
            height = Math.max(height, calculateMaxTabHeight(tabPlacement));
            tabExtent = preferredTabAreaWidth(tabPlacement, height - tabAreaInsets.top - tabAreaInsets.bottom);
            width += tabExtent;
            break;
        case TOP:
        case BOTTOM:
        default:
            width = Math.max(width, calculateMaxTabWidth(tabPlacement));
            tabExtent = preferredTabAreaHeight(tabPlacement, width - tabAreaInsets.left - tabAreaInsets.right);
            height += tabExtent;
    }