JTabbedPane的尺寸问题和固定高度的内容 [英] Size issues with JTabbedPane and fixed height content

查看:202
本文介绍了JTabbedPane的尺寸问题和固定高度的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在编写此问题时,我已经找到了一种使它按照我想要的方式运行的方法.基于,我仍在发布此问题,因为其他人可能会遇到类似的问题.

While writing this question I have been able to find a way to get it to behave the way I wanted. Based on this, I am still posting the question as other people might face similar issues.

对于用于水平延伸但具有固定高度的内容的JTabbedPane的大小,我遇到以下问题. setTabLayoutPolicy()的两个选项似乎都会改变内容的高度,并且不会始终以其首选高度或最小高度显示内容.

I have the following issues with the sizing of a JTabbedPane used for content that stretches horizontally but has a fixed height. Both options for setTabLayoutPolicy() seem to alter the height of the content and won’t consistently display it at its preferred or minimum height.

使用默认值WRAP_TAB_LAYOUT时,选项卡窗格的首选大小并未考虑这些选项卡当前是堆叠还是彼此相邻显示,如此处此错误报告.如果选项卡式窗格是基于堆叠的选项卡进行布局的,则当有足够的空间可让这些选项卡彼此相邻显示时,添加的每个选项卡的内容高度都会增加大约20个像素(一个选项卡的高度).如果选项卡式窗格是根据彼此相邻显示的选项卡进行布局的,则当必须堆叠这些选项卡时,内容高度会降低.

With the default WRAP_TAB_LAYOUT, the preferred size of the tab pane does not take into account whether the tabs are actually stacked or displayed next to each other at the moment, as discussed here, here and in this bug report. If the tabbed pane is laid out based on stacked tabs, the height of the content is increased by about 20 pixels (height of one tab) for each tab added when there is enough space for the tabs to be displayed next to each other. If the tabbed pane is laid out based on tabs being displayed next to each other, the content height is reduced when the tabs have to be stacked.

当策略设置为SCROLL_TAB_LAYOUT时,选项卡栏的高度是固定的,布局基本上是正确的.但是,根据外观,选项卡内容的大小会减少几个像素.我已经发现这是由于L& F所定义的选项卡区域的插入而引起的,这些未计入选项卡窗格的首选大小计算中(请参阅适用于某些L& F(例如Metal),但不适用于其他L& F(例如Nimbus).

When the policy is set to SCROLL_TAB_LAYOUT, the height of the tab bar is fixed and the layout is mostly correct. However, depending on the look and feel, the size of the tab content is reduced by a few pixels. I have been able to find out that this is due to the insets of the tab area as defined by the L&F, which are not factored into the preferred size calculation of the tab pane (see this bug report). Setting UIManager.getDefaults().put("TabbedPane.tabAreaInsets", new Insets(0,0,0,0)) works for some L&F (e.g. Metal) but not for others (e.g. Nimbus).

似乎只有以下选项:

  • 使用堆叠的标签,并为内容添加额外的高度
  • 使用堆叠的标签,并在空间不足时覆盖内容
  • 使用滚动的标签,并在标签内容的最小/首选尺寸中添加几个像素,从而使每个L&F看起来都有些不同(但至少不应截断内容)
  • 使用滚动的选项卡,并将选项卡式窗格的UI设置为新的BasicTabbedPaneUI,效果看起来不太好
  • use stacked tabs and have extra height added to the content
  • use stacked tabs and have the content covered when there is not enough space
  • use scrolled tabs and add a few pixels to the minimum/preferred size of the tab content, making it look a bit different with each L&F (but at least the content should not be cut off)
  • use scrolled tabs and set the UI of the tabbed pane to a new BasicTabbedPaneUI which does not look that great

是否有一种干净的方法来强制选项卡式窗格的内容始终以固定的高度显示?

以下代码和屏幕截图说明了问题

The following code and screenshots illustrate the problem

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.UIManager;

public class TabbedPaneTest extends JFrame {

    TabbedPaneTest() {

        JPanel mainPanel = new JPanel();
        mainPanel.setBackground(Color.white);

        JTabbedPane tabs = new JTabbedPane();
        //tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); // content cut off by a few pixels
        tabs.setTabPlacement(JTabbedPane.BOTTOM);

        Dimension min  = new Dimension(100,200);
        Dimension max = new Dimension(Short.MAX_VALUE,Short.MAX_VALUE);
        //Dimension pref = new Dimension(Short.MAX_VALUE,200); // content cut off when small
        Dimension pref = new Dimension(0,200); // content gets extra space when large

        int tabCount = 3;
        for (int i = 0; i < tabCount; i++) {
            JLabel content = new JLabel();
            content.setMinimumSize(min);
            content.setMaximumSize(max);
            content.setPreferredSize(pref);
            tabs.addTab("lorem ipsum dolor sit amet", content);
        }

        // set up and render window
        getContentPane().add(mainPanel, BorderLayout.CENTER);
        getContentPane().add(tabs, BorderLayout.PAGE_END);
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("JScrollPane Test");
        pack();
        setSize(700,400);

        tabs.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                JTabbedPane tabbedPane = (JTabbedPane) e.getComponent();
                int tabCount = tabbedPane.getTabCount();
                for (int i = 0; i < tabCount; i++) {
                    Component c = tabbedPane.getComponentAt(i);
                    ((JLabel) c).setText("<html>"
                            + getSizes(c, "content")
                            + getSizes(tabbedPane, "tabs")
                            + "</html>");
                }
            }
        });
    }

    private static String getSizes(Component c, String name) {
        return "<p>" + name + " - "
                + "  minimum:" + Integer.toString(c.getMinimumSize().width)
                         + "x" + Integer.toString(c.getMinimumSize().height)
                + "  maximum:" + Integer.toString(c.getMaximumSize().width)
                         + "x" + Integer.toString(c.getMaximumSize().height)
                + "  preferred:" + Integer.toString(c.getPreferredSize().width)
                         + "x" + Integer.toString(c.getPreferredSize().height)
                + "  actual:" + Integer.toString(c.getSize().width)
                         + "x" + Integer.toString(c.getSize().height)
                + "</p>";
    }

    public static void main(String args[]) {

        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(TabbedPaneTest.class
                    .getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override public void run() {
                new TabbedPaneTest().setVisible(true);
            }
        });
    }

}

使用滚动标签,内容被剪切了几个像素(193px,而不是200px):

With scrolled tabs, the content is cut off by a few pixels (193px instead of 200px here):

具有堆叠的标签页和宽内容,当窗口较小时(此处为160像素,而不是200像素),内容将被截断:

With stacked tabs and wide content, the content is cut off when the window is small (160px instead of 200px here):

具有堆叠的选项卡和狭窄的内容,当窗口较大时(此处为240px而不是200px),内容会变大:

With stacked tabs and narrow content, the content is made larger when the window is large (240px instead of 200px here):

推荐答案

在详细了解了计算选项卡式窗格的首选大小的方式之后,我已经能够针对WRAP_TAB_LAYOUT情况提出以下解决方案

After reading more about the way the preferred size of the tabbed pane is calculated, I have been able to come up with the following solution for the WRAP_TAB_LAYOUT case.

问题是对于选项卡式窗格,首选的高度和宽度是耦合的.首选高度是为首选宽度计算的,而不是实际的当前宽度.如果父级的布局管理器尊重首选的高度,而不尊重首选的宽度,这是有问题的.

The problem is that for the tabbed pane, the preferred height and width are coupled. The preferred height is calculated for the preferred width and not for the actual, current width. This is problematic if the layout manager of the parent respects the preferred height but not the preferred width.

我想到的解决方案是设置一个侦听器,该侦听器将每个选项卡内容的首选宽度设置为其当前宽度.这样,选项卡式窗格可以正确计算其首选高度,并且可以进行布局,例如带有BorderLayout.

The solution I came up with is to set up a listener that sets the preferred width of each tab content to its current width. This way, the tabbed pane calculates its preferred height correctly and can be laid out e.g. with a BorderLayout.

tabs.addComponentListener(new ComponentAdapter() {
    @Override
    public void componentResized(ComponentEvent e) {
        JTabbedPane tabbedPane = (JTabbedPane) e.getComponent();
        int tabCount = tabbedPane.getTabCount();
        for (int i = 0; i < tabCount; i++) {
            Component c = tabbedPane.getComponentAt(i);
            c.setPreferredSize(new Dimension(c.getSize().width, c.getPreferredSize().height));
        }
    }
});

对于SCROLL_TAB_LAYOUT案,我还没有找到令人满意的解决方案,因此,如果有人有想法,将不胜感激.

I haven’t been able to find a satisfactory solution to the SCROLL_TAB_LAYOUT case yet, so if anyone has an idea it would be appreciated.

这篇关于JTabbedPane的尺寸问题和固定高度的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆