首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >空JTabbedPane

空JTabbedPane
EN

Stack Overflow用户
提问于 2014-07-03 16:09:46
回答 1查看 1.2K关注 0票数 4

我在创建一个空的JTabbedPane时遇到了一个问题,在这个上唯一能看到的部分是行选项卡。

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

目前的解决办法是覆盖getPreferredSize(),但在我看来,这似乎很疯狂。注释掉重写的方法,以了解我的意思。

我漏掉了什么明显的东西吗?

背景:

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

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

代码语言:javascript
复制
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 {}
}
EN

回答 1

Stack Overflow用户

发布于 2014-07-03 17:01:56

问得好!但是很容易就能了解到正在发生的事情。

问题是,您的内容没有最小宽度,首选大小没有设置,选项卡位置是顶部/底部,UI是默认的。

由于未设置首选大小,那么当重新验证布局时,所需空间的计算将进入BasicTabbedPaneUI方法Dimension calculateSize(false)

内容如下:

代码语言:javascript
复制
int height = 0;
int width = 0;
<other vars>
// Determine minimum size required to display largest
// child in each dimension
<actual method>

在这里,它计算容纳任何子级的最小大小,并将其存储在高度/宽度中。在您的例子中,这会产生类似于10,10的结果(因为我认为是单个标签选项卡创建者,所以我没有遵循这个选项卡)。

然后发生了魔法:

代码语言:javascript
复制
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中额外的高度的来源。本质上是因为水平制表符的位置,它首先关心的是宽度,然后是高度。

如何修复:

  1. 设置一个首选的大小:)我知道很多人说不要设置首选的大小,但在这种情况下,这只会起作用。由于设置了首选大小(通过实际设置,而不是覆盖getPreferredSize()),代码将永远无法计数选项卡。
  2. 给至少一个您的孩子一个大小(通过setPreferredSize或覆盖getPreferredSize)。如果其中一个子行的宽度是帧的宽度,或者是底部的表的宽度,那么TabbedPane将不会为每个选项卡分配额外的行,因为一行将适合所有选项卡。
  3. 为选项卡窗格创建自己的UI。虽然实际上,我从来没有这样做过,但是制作您自己的选项卡式窗格可能更容易。

编辑:

在进一步考虑了这一点之后,我意识到解决方案1您自己的解决方案存在缺陷,如果选项卡式窗格确实需要为制表符多行(hello调整大小),那么坏的事情就会发生。别用它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24558662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档