为什么此 Swing List 不显示其元素?
我正在为这个问题摸不着头脑。下面是一个运行示例。我在流布局中有 2 个 Swing 列表,每个列表都有一个简单的数据模型。根据我实例化 FlowLayout 的方式,第二个列表不会显示其元素。诡异的。
import javax.swing.*;
import java.awt.*;
public class ListboxTest2 {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
// this works
// panel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
// this doesn't
panel.setLayout(new FlowLayout());
final JList list1 = new JList();
list1.setPreferredSize(new Dimension(120, 60));
final JList list2 = new JList();
list2.setPreferredSize(new Dimension(120, 60));
final String[] strings1 = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12"};
final String[] strings2 = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12"};
list1.setModel(new AbstractListModel() {
public int getSize() {
return strings1.length;
}
public Object getElementAt(int index) {
return strings1[index];
}
});
panel.add(list1);
list2.setModel(new AbstractListModel() {
public int getSize() {
return strings2.length;
}
public Object getElementAt(int index) {
return strings2[index];
}
});
panel.add(list2);
f.add(panel);
f.setVisible(true);
list1.grabFocus();
list1.setSelectedIndex(0);
}
}
I'm scratching my head over this one. Below is a running sample. I have 2 Swing Lists in a flow layout each with a simple data model. Depending on how I instantiate the FlowLayout the 2nd List does not display its elements. Weird.
import javax.swing.*;
import java.awt.*;
public class ListboxTest2 {
public static void main(String[] args) {
JFrame f = new JFrame();
f.setSize(500, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
// this works
// panel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));
// this doesn't
panel.setLayout(new FlowLayout());
final JList list1 = new JList();
list1.setPreferredSize(new Dimension(120, 60));
final JList list2 = new JList();
list2.setPreferredSize(new Dimension(120, 60));
final String[] strings1 = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12"};
final String[] strings2 = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12"};
list1.setModel(new AbstractListModel() {
public int getSize() {
return strings1.length;
}
public Object getElementAt(int index) {
return strings1[index];
}
});
panel.add(list1);
list2.setModel(new AbstractListModel() {
public int getSize() {
return strings2.length;
}
public Object getElementAt(int index) {
return strings2[index];
}
});
panel.add(list2);
f.add(panel);
f.setVisible(true);
list1.grabFocus();
list1.setSelectedIndex(0);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这与布局管理器无关。在使其可见之前,您需要在
JFrame
上调用pack()
,否则行为会有些随机,因为主线程和 EDT 之间存在竞争条件。理论上,所有 UI 操作都必须在 EDT 中进行,包括原始设置。实际上,您可以通过在 EDT 开始之前完全完成设置来避免这种情况(我相信这通常发生在第一个组件可见时)。我怀疑在您的代码中,
grabFocus()
会导致在主线程上计算 UI 布局,然后导致与setVisible() 启动的 EDT 发生竞争条件
。This has nothing to do with the layout manager. You need to call
pack()
on theJFrame
before you make it visible, otherwise the behaviour is somewhat random because you have a race condition between your main thread and the EDT.Theoretically, all manipulation of the UI must happen in the EDT, including the original setup. In practice, you can avoid this by doing the setup completely before the EDT starts (which I believe usually happens when the first component is made visible). I suspect that in your code, the
grabFocus()
causes the layout of the UI to be computed on the main thread, which then results in a race condition with the EDT started bysetVisible()
.在第一次尝试中,第二个列表仅显示一个元素。
在所有后续尝试中,它都正确显示。
奇怪的。
我会尝试在初始化的其余部分之后移动 setVisible(true) 。
in the first attempt, the second list only displayed one element.
in all subsequent attempts, it displayed it correctly.
strange.
I would try to move setVisible(true) after the rest of the initialization.
将列表框包装在 JScrollPane 中始终是一个好习惯,因为它允许您在项目超出可见区域时滚动。像这样将列表框添加到面板中。
It is always a good practice to wrap listboxes within a JScrollPane as it would allow you to scroll when items exceed the visible area. Add the list boxes to panel like this.