如果在组件上使用setPreferredSize(),则会修复宽度和高度。因此,如果我只想要一个固定的宽度,并根据需要调整高度以将内容容纳到该约束宽度中,这是不好的。
考虑一段HTML文本。在浏览器窗口中,字符串将自动换行并调整其所需的高度,以使其适合可用宽度。因此,如果我们要修复浏览器的宽度,文本的高度将保持不变。
使用组件可以实现同样的目标吗?具体来说,是JPanel。
请注意,我相信setMaximumSize()会做我想要的 - 让我设置一个最大宽度,并将高度设置为巨大的,以便它永远不会比我指定的更宽,但有足够的高度成长为。但是,系统似乎完全忽略了该功能。例如:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JViewport;
public class TMSApp
{
public static void main(String[] args)
{
JFrame frame = new JFrame("TestMaximumSize");
Container container = frame.getContentPane();
container.setBackground(Color.RED);
container.setLayout(new BorderLayout() );
JViewport viewport = new JViewport();
viewport.setBackground(Color.BLACK);
viewport.setPreferredSize(new Dimension(640, 480) );
container.add(viewport, BorderLayout.CENTER);
JPanel testPanel = new JPanel();
testPanel.setBackground(Color.WHITE);
testPanel.setMaximumSize(new Dimension(100, 9999) );
//testPanel.setPreferredSize(new Dimension(100, 9999) );
viewport.setView(testPanel);
testPanel.setLayout(new BoxLayout(testPanel, BoxLayout.Y_AXIS) );
testPanel.add(new JLabel("<html>This is a very long HTML label "
+ "that should adapt to the width of "
+ "the parent container by wrapping text, "
+ "just as it would in a web page "
+ "constrained to the window width.</html>") );
frame.setVisible(true);
frame.pack();
}
}
如果您运行此应用程序,尽管我说'不超过100',testPanel会尽可能宽地将标签留在一行上。对我来说,这打破了setMaximumSize()的契约。
(注意,如果你使用setPreferredSize(), 正确地约束它 - 但我们不能在上面提到的组件上使用setPreferredSize(),因为它也修复了高度而不是给出它有些流动性 - 是的,setMaximumSize()最终会限制高度,但这是可以接受的。)
知道如何控制宽度但是根据需要保持高度以适应吗?
(为了记录,我想将一堆面板添加到包裹在JScrollPane中的更大的面板,因此充当一个带有面板而不是标签的列表。我认为必须向侧面滚动大面板以查看所有面板item是一个糟糕的UI,所以我希望宽度不比滚动窗格的实际可显示区域没有滚动条宽,因此让较小的面板调整它们的高度以适应它们的内容 - 带有HTML字符串的JLabel - 进入因此,用户只需垂直滚动即可查看所有项目。如上所示,即使手动使用视口+滚动条也会遇到同样的问题。
如果我只能修复较大面板的宽度,则较小的子面板会自动受宽度约束;或者,如果我只能修复子面板的宽度,那么较大的面板将永远不会比我想要的更宽。)
答案 0 :(得分:1)
我添加了对SwingUtilities的调用,以确保您的Swing组件位于Event Dispatch Thread上。
我让你的GUI工作,但你需要小心testPanel的高度。如果您只需设置首选宽度或首选高度而不必同时设置两者,那么摆动会更好。
这是我的代码版本。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
public class TMSApp implements Runnable {
@Override
public void run() {
JFrame frame = new JFrame("TestMaximumSize");
Container container = frame.getContentPane();
container.setBackground(Color.RED);
container.setLayout(new BorderLayout());
JPanel testPanel = new JPanel();
testPanel.setBackground(Color.WHITE);
testPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
testPanel.setPreferredSize(new Dimension(250, 9999));
testPanel.setLayout(new BoxLayout(testPanel, BoxLayout.Y_AXIS));
testPanel.add(new JLabel("<html>This is a very long HTML label "
+ "that should adapt to the width of "
+ "the parent container by wrapping text, "
+ "just as it would in a web page "
+ "constrained to the window width.</html>"));
JScrollPane scrollPane = new JScrollPane(testPanel);
scrollPane.setHorizontalScrollBarPolicy(
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.getViewport().setPreferredSize(new Dimension(250, 400));
container.add(scrollPane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new TMSApp());
}
}