gpt4 book ai didi

java - 返回 JComponent 的实际大小,如显示的那样

转载 作者:行者123 更新时间:2023-11-29 04:01:11 24 4
gpt4 key购买 nike

晚上好

我想知道如何在使用 LayoutManager 布置 JComponent 后获取它的大小。我读到这是可能的,只要您事先调用 dolayout()、validate() 或 setVisible()。但是,我无法在我的代码中使用它。

我想知道这一点的原因是只添加适合框架设置大小的尽可能多的组件,而事先不知道组件的大小。调用 validate() 不会设置此代码示例中组件的大小。关于如何获得合适尺寸的任何想法?

public class TestFrame extends JFrame {

public static void main(String args[]) {
TestFrame frame = new TestFrame();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public TestFrame() {
super("Test Frame");
super.setSize(300, 600);
this.addComponents();
}

private void addComponents() {

int heightLeft = this.getHeight();
JPanel panel = new JPanel();
panel.setSize(300, 600);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
String text = "This is a long String that represents "
+ "the length of strings in my application. "
+ "This will vary in the real application."
+ "<ul><li>It uses html</li><li>not just</li>"
+ "<li>plain text</li></ul>"
+ "I'd like as many as will fit in the fame to be added.\n";

while (true) {
JTextPane textPane = createTextPane(text);

this.invalidate();

if (heightLeft > 0) {
panel.add(textPane);
} else {
break;
}
System.out.println("Before validation:" + textPane.getSize());
// returns width and height = 0
this.validate();
System.out.println("After validation:" + textPane.getSize());
// Still returns width and height = 0
heightLeft -= textPane.getPreferredSize().getHeight();
}

super.add(panel);
}

public JTextPane createTextPane(String text) {
JTextPane textPane = new JTextPane();

textPane = new JTextPane();
textPane.setEditorKit(new StyledEditorKit());
textPane.setEditable(false);
textPane.setOpaque(false);

textPane.setContentType("text/html");
textPane.setText(text);

return textPane;
}
}

感谢您的宝贵时间!

最佳答案

您要完成的任务似乎出奇地困难,因为您必须依靠 Swing 的方法来计算各种组件的大小,然后设法获取正确的值以对它们执行计算。虽然根据可用的 API 方法,它看起来相当微不足道,但只要看一眼源代码就会发现不同的故事。由于某些值仅在实际显示组件时才能正确计算,这意味着您之前尝试获得的值并不代表您在屏幕上看到的内容(正如您发现的那样),这使情况变得更加复杂。

除此之外,似乎应该可以实现您的目标。请记住,当向 BoxLayout 添加元素时,预期的行为是您分配了布局管理器的容器的整个空间用于定位子组件。这意味着当您将 JTextPane 对象添加到您的 JPanel 时,它们将拉伸(stretch),以便它们的总高度占据您指定的所有 600 像素。因此,您需要以稍微不同的方式确定何时超出了可用高度,因为每个组件的渲染高度可能会在进程中发生变化。

在玩弄它并反复诅咒 Swing 之后,我想出了一个解决方案,方法是使用 getBounds()(BoxLayout 在委托(delegate)中使用到它的 LayoutParameters 来确定组件高度),但我发现这个方法不是很可靠。我将继续研究它,所以希望我能提出一些可用的代码,或者其他人会提出我忽略的解决方案。

编辑:为了完整起见,这里有一个代码示例,它调用 doLayout() 在显示表单之前计算必要的大小(仍然有 BoxLayout 的缺点)。由于 SizeRequirements 中的某些 ArrayIndexOutOfBoundsException,它无法在我的 JRE 1.5 上运行,但该错误似乎已在 1.6 中修复。在 1.5 中,如果你的组件列表不是太大,你可以将它们全部添加,在循环之后调用 doLayout()(因为无论出于何种原因这似乎在 1.5 中工作),然后遍历getComponents() 返回的数组,在超过最大高度后删除所有内容。

最后一点,我个人非常喜欢使用 MigLayout对于更复杂的布局,因为我发现它的定位和样式机制比当前的内置布局管理器更容易使用。在这里并不过分相关,但无论如何值得一提。

import java.awt.Dimension;
import java.awt.Rectangle;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.text.StyledEditorKit;

public class TestFrame extends JFrame {
private static final int CONTENT_HEIGHT = 600;
private static final int CONTENT_WIDTH = 300;

public static void main(String[] args) {
TestFrame frame = new TestFrame();

frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public TestFrame() {
super("Test Frame");
this.addComponents();
this.pack();
}

private void addComponents() {
JPanel panel = new JPanel();

panel.setPreferredSize(new Dimension(CONTENT_WIDTH, CONTENT_HEIGHT));
panel.setBounds(new Rectangle(CONTENT_WIDTH, CONTENT_HEIGHT));
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

String text = "This is a long String that represents the length of" +
" stings in my application. This will vary in the real" +
" application.<ul><li>It uses html</li><li>not just</li>" +
"<li>plain text</li></ul>I'd like only as many as will fit" +
" in the fame to be added.\n";

this.setContentPane(panel);

int height = 0;

while(height < CONTENT_HEIGHT) {
JTextPane textPane = createTextPane(text);

panel.add(textPane);
panel.doLayout();

// The height on the preferred size has been set to reflect
// the rendered size after calling doLayout()
height += textPane.getPreferredSize().getHeight();

// If we've exceeded the height, backtrack and remove the
// last text pane that we added
if (height > CONTENT_HEIGHT) {
panel.remove(textPane);
}
}
}

private JTextPane createTextPane(String text) {
JTextPane textPane = new JTextPane();

textPane.setEditorKit(new StyledEditorKit());
textPane.setEditable(false);
textPane.setOpaque(false);
textPane.setContentType("text/html");
textPane.setText(text);

return textPane;
}
}

关于java - 返回 JComponent 的实际大小,如显示的那样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3482379/

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