返回 JComponent 的实际大小,如显示的那样
晚上好,
我想知道如何在使用 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;
}
}
感谢您抽出时间!
Good evening,
I'd like to know how to get the size of a JComponent after it's been laid out with a LayoutManager. I've read that this is possible, if you just call dolayout(), validate(), or setVisible() beforehand. However, I can't get it to work in my code.
The reason I'd like to know this is to only add as many components as will fit in the frame's set size, while not knowing the size of the components beforehand. Calling validate() doesn't set the size of the components in this code sample. Any ideas on how I can get the right size?
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;
}
}
Thanks for your time!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您想要完成的任务似乎出奇地困难,因为您必须依赖 Swing 的方法来计算各个组件的大小,然后设法获取正确的值来对它们执行计算。虽然根据可用的 API 方法,它看起来相当微不足道,但浏览一下源代码就会发现不同的情况。由于某些值仅在组件实际显示时才能正确计算,这意味着您在此之前尝试获取的值并不代表您在屏幕上看到的内容(正如您所发现的),这一事实使情况变得更加复杂。
除此之外,似乎应该可以实现您的目标。但请记住,当向
BoxLayout
添加元素时,预期的行为是您分配了布局管理器的容器的整个空间都用于定位子组件。这意味着,当您将JTextPane
对象添加到JPanel
时,它们将会拉伸,以便它们的总高度占据您指定的全部 600 个像素。因此,您需要以稍微不同的方式确定何时超出可用高度,因为每个组件的渲染高度可能会在进程中发生变化。经过一番尝试并反复咒骂 Swing 后,我虽然已经通过使用 getBounds() 提出了一个解决方案(
BoxLayout
用于委托其getBounds()
)。 code>LayoutParameters 来确定组件高度),但事实证明我的方法不是很可靠。我将继续尝试它,所以希望我能提出一些可用的代码,或者其他人会提出我忽略的解决方案。编辑:为了完整起见,这里有一个代码示例,它调用
doLayout()
在显示表单之前计算必要的尺寸(仍然存在BoxLayout
的缺点>)。由于SizeRequirements
中的一些ArrayIndexOutOfBoundsException
,它无法在我的 JRE 1.5 上运行,但该错误似乎已在 1.6 中修复。在 1.5 中,如果您的组件列表不是太大,您可以将它们全部添加,在循环后调用doLayout()
(因为无论出于何种原因,这似乎在 1.5 中都有效),然后只需遍历getComponents()
返回的数组,在超过最大高度后删除所有内容。最后一点,我个人喜欢使用 MigLayout 来实现更复杂的布局,因为我发现它定位和样式机制比当前的内置布局管理器更容易使用。这里不太相关,但无论如何值得一提。
What you're trying to accomplish seems to be surprisingly difficult, because you have to rely on Swing's method of calculating the size of your various components, and then manage to get the correct values out to perform the calculations on them. While it looks fairly trivial based on the available API methods, a glance at the source code reveals a different story. This is additionally complicated by the fact that some values are only correctly calculated when the component is actually displayed, meaning that the values you try to get before that aren't representative of what you see on the screen (as you found out).
That aside, it seems like it should be possible to do what you're aiming for. Keep in mind though that when adding elements to a
BoxLayout
, the expected behaviour is that the entire space of the container to which you've assigned the layout manager is utilized in positioning the child components. This means that as you addJTextPane
objects to yourJPanel
, they will stretch so that their summed heights takes up all 600 pixels you've specified. As a result, you need to go about determining when you've exceeded the available height a little differently, since the rendered height of each component might change in-process.After playing around with it a little and cursing Swing repeatedly, I had though I had come up with a solution by using
getBounds()
(whichBoxLayout
uses in delegation to itsLayoutParameters
to determine the component height), but the method I had turned out to not be very reliable. I'm going to keep playing around with it, so hopefully I'll come up with some usable code, or someone else will come along with a solution that I've overlooked.Edit: For completeness, here's a code sample that calls
doLayout()
to calculate the necessary sizes before showing the form (still with the drawbacks ofBoxLayout
). It won't run on my JRE 1.5 due to someArrayIndexOutOfBoundsException
inSizeRequirements
, but that bug seems to have been fixed in 1.6. In 1.5, if your list of components wasn't too large, you could add them all, calldoLayout()
after the loop (as this seems to work in 1.5 for whatever reason), then just traverse the array returned bygetComponents()
, removing everything after the maximum height has been exceeded.As a final note, I'm personally a fan of using MigLayout for more complex layouts, since I find its positioning and styling mechanism a bit easier to work with than the current built-in layout managers. Not overly relevant here, but worth a mention anyway.
显示组件的框架必须可见才能获取尺寸(因为如果框架不可见,布局管理器会将尺寸设置为 (0, 0))。在添加组件之前,您必须调用
frame.setVisible(true)
。我还建议您创建自己的面板类(它将扩展 JPanel)并创建组件并从那里将它们放在面板上,而不是从主类中。The frame on which the components are displayed must be visible in order to get the size (because if the frame is not visible, layout manager sets the size to (0, 0)). You must call
frame.setVisible(true)
before adding the components. I also recommend that you make your own panel class (which would extend JPanel) and to create components and put them on panel from there, not from the main class.