gpt4 book ai didi

java - JTabbedPane 和固定高度内容的大小问题

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:16:16 31 4
gpt4 key购买 nike

在写这个问题时,我找到了一种方法让它按照我想要的方式运行。基于this ,我仍然发布问题,因为其他人可能会遇到类似的问题。

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

使用默认的 WRAP_TAB_LAYOUT,选项卡 Pane 的首选大小不考虑选项卡目前是实际堆叠还是彼此相邻显示,如讨论的那样 here , herethis bug report .如果选项卡式 Pane 基于堆叠选项卡进行布局,则当有足够的空间让选项卡彼此相邻显示时,每添加一个选项卡,内容的高度就会增加大约 20 像素(一个选项卡的高度)。如果选项卡式 Pane 的布局是基于彼此相邻显示的选项卡,则当必须堆叠选项卡时,内容高度会降低。

当策略设置为 SCROLL_TAB_LAYOUT 时,标签栏的高度是固定的,布局基本正确。但是,根据外观,选项卡内容的大小会减少几个像素。我已经能够发现这是由于 L&F 定义的选项卡区域的插入,这没有被考虑到选项卡 Pane 的首选大小计算中(参见 this bug report )。设置 UIManager.getDefaults().put("TabbedPane.tabAreaInsets", new Insets(0,0,0,0)) 适用于某些 L&F(例如 Metal)但不适用于其他(例如 Nimbus) .

好像只有下面几个选项:

  • 使用堆叠标签并向内容添加额外的高度
  • 使用堆叠标签,并在空间不足时覆盖内容
  • 使用滚动标签并在标签内容的最小/首选尺寸上添加几个像素,使其在每个 L&F 中看起来都有些不同(但至少内容不应被截断)
  • 使用滚动选项卡并将选项卡式 Pane 的 UI 设置为新的 BasicTabbedPaneUI,这看起来不太好

是否有一种简洁的方法来强制选项卡式 Pane 的内容始终以固定高度显示?

下面的代码和截图说明了问题

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);
}
});
}

}

对于滚动标签,内容被截断了几个像素(此处为 193 像素而不是 200 像素):

screenshot with scrolled tabs

对于堆叠的选项卡和宽内容,当窗口较小时内容被截断(此处为 160px 而不是 200px):

enter image description here

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

enter image description here

最佳答案

在详细了解选项卡式 Pane 的首选大小的计算方式后,我已经能够为 WRAP_TAB_LAYOUT 案例提出以下解决方案。

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

我想到的解决方案是设置一个监听器,将每个选项卡内容的首选宽度设置为其当前宽度。这样,选项卡式 Pane 可以正确计算其首选高度,并且可以进行布局,例如使用 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 案例,我还没有找到令人满意的解决方案,所以如果有人有想法,我们将不胜感激。

关于java - JTabbedPane 和固定高度内容的大小问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34944950/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com