我在创建一个空的JTabbedPane时遇到了一个问题,在这个上唯一能看到的部分是行选项卡。
每次我添加一个带有“空”组件的新选项卡时,JTabbedPane的高度都会增加,但为什么呢?
目前的解决办法是覆盖getPreferredSize(),但在我看来,这似乎很疯狂。注释掉重写的方法,以了解我的意思。
我漏掉了什么明显的东西吗?
背景:
我们需要一个JTabbedPane,其中选项卡窗格从2个选项卡开始,但用户可以根据需要添加更多选项卡,最多10个。此外,每个选项卡包含相同的组件,但数据不同。这个决定是伪造一个JTabbedPane的外观,只为这个外观实现一个空的JTabbedPane,并且使用一个固定的JPanel,它的内容将根据单击的选项卡刷新。
(通常,我可以重新创建JPanel n次,但对于控制UI的演示类来说,这将是噩梦,这超出了我的问题范围。)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CustomTabbedPane implements Runnable
{
static final int MAX_TABS = 11; // includes the "add" tab
JPanel pnlTabs;
JTabbedPane tabbedPane;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new CustomTabbedPane());
}
public void run()
{
JPanel p = buildPanel();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(p);
frame.setSize(800,400);
frame.setVisible(true);
}
private JPanel buildPanel()
{
tabbedPane = new JTabbedPane()
{
@Override
public Dimension getPreferredSize()
{
Dimension dim = super.getPreferredSize();
dim.height = getUI().getTabBounds(this, 0).height + 1;
return dim;
}
};
tabbedPane.addTab("Tab 1", getEmptyComp());
tabbedPane.addTab("Tab 2", getEmptyComp());
tabbedPane.addTab("+", new TabCreator());
tabbedPane.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
addTab();
}
});
JScrollPane scroll = new JScrollPane(new JTable(5,10));
JPanel p = new JPanel(new BorderLayout());
p.add(tabbedPane, BorderLayout.NORTH);
p.add(scroll, BorderLayout.CENTER);
p.setBorder(BorderFactory.createLineBorder(Color.BLUE.darker(), 1));
return p;
}
private void addTab()
{
if (tabbedPane.getSelectedComponent() instanceof TabCreator)
{
int selIndex = tabbedPane.getSelectedIndex();
if (tabbedPane.getComponentCount() < MAX_TABS)
{
if (selIndex == tabbedPane.getComponentCount()-1)
{
String title = "Tab " + (selIndex + 1);
tabbedPane.insertTab(title, null, getEmptyComp(), "", selIndex);
tabbedPane.setSelectedIndex(selIndex);
if (tabbedPane.getComponentCount() == MAX_TABS)
{
tabbedPane.setEnabledAt(MAX_TABS-1, false);
}
}
}
}
}
private Component getEmptyComp()
{
return Box.createVerticalStrut(1);
}
class TabCreator extends JLabel {}
}发布于 2014-07-03 17:01:56
问得好!但是很容易就能了解到正在发生的事情。
问题是,您的内容没有最小宽度,首选大小没有设置,选项卡位置是顶部/底部,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>在这里,它计算容纳任何子级的最小大小,并将其存储在高度/宽度中。在您的例子中,这会产生类似于10,10的结果(因为我认为是单个标签选项卡创建者,所以我没有遵循这个选项卡)。
然后发生了魔法:
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;
}这里的情况是,它将首选宽度设置为最大制表符宽度和最大子宽度的最大值。在你的例子中,标签文本大约是44。然后计算tabExtent来查看需要多少行制表符才能支持这个首选宽度。在您的情况下-它是额外的一行标签为每个标签。这就是preferredSize().height中额外的高度的来源。本质上是因为水平制表符的位置,它首先关心的是宽度,然后是高度。
如何修复:
getPreferredSize()),代码将永远无法计数选项卡。setPreferredSize或覆盖getPreferredSize)。如果其中一个子行的宽度是帧的宽度,或者是底部的表的宽度,那么TabbedPane将不会为每个选项卡分配额外的行,因为一行将适合所有选项卡。编辑:
在进一步考虑了这一点之后,我意识到解决方案1和您自己的解决方案存在缺陷,如果选项卡式窗格确实需要为制表符多行(hello调整大小),那么坏的事情就会发生。别用它。
https://stackoverflow.com/questions/24558662
复制相似问题