Java JDialog中的组件未显示
首先:我知道这个问题似乎被问了几百万次,但其他问题的答案似乎都不适合我 有时,当我在下面的代码中运行Java JDialog中的组件未显示,java,swing,jdialog,Java,Swing,Jdialog,首先:我知道这个问题似乎被问了几百万次,但其他问题的答案似乎都不适合我 有时,当我在下面的代码中运行Message.popup(String,int)时,文本显示正确,但有时JDialog是空的,就像根本没有添加组件一样 public class Message extends JDialog { private int width; private int height; private JLabel content; public Message(Stri
Message.popup(String,int)
时,文本显示正确,但有时JDialog是空的,就像根本没有添加组件一样
public class Message extends JDialog {
private int width;
private int height;
private JLabel content;
public Message(String _content, int _margin) {
super();
this.content = new JLabel(_content);
content.setFont(new Font("Monospaced", Font.BOLD, 20));
this.margin = _margin;
this.width = content.getPreferredSize().width + _margin;
this.height = content.getPreferredSize().height + _margin;
createComponents();
setProperties();
}
public static void popup(String _content, int _time) {
if (SwingUtilities.isEventDispatchThread()) {
runPopup(_content, _time);
}
else {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
runPopup(_content, _time);
}
});
}
}
private static void runPopup(String _content, int _time) {
final Message message = new Message(_content);
new Timer(_time, new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
message.dispose();
}
}).start();
}
private void createComponents() {
setLayout(new BorderLayout());
Box box = Box.createHorizontalBox();
box.add(Box.createHorizontalGlue());
box.add(content, BorderLayout.CENTER);
box.add(Box.createHorizontalGlue());
add(box);
}
private void setProperties() {
setSize(width, height);
setLocation(Coordinator.calculateCenteredWindowLocation(width, height));
setUndecorated(true);
setResizable(false);
setTitle(content.getText());
setVisible(true);
update(getGraphics());
}
}
没有
更新(getGraphics())代码>,帧总是空的,但有了它,它取决于风向。。。(如图所示!)您确定您的代码正在中执行吗?事实上,如果不是(这就是我所期望的,因为您睡眠
当前线程,Swing通常不喜欢什么),那么您的帧将难以渲染
为了避免这些典型的Swing线程问题,请查看该类,它为您提供了确保在EDT中运行的方法。此外,您可以使用Swing(注意不要将其与java.util.Timer
混淆)来重新封装线程,而不是直接休眠线程。如@Riduidel所述,在事件调度线程或EDT
上发生任何与Swing相关的事件都很重要。这是因为Swing不是线程安全的。调用popup()
时,应执行以下操作
if(SwingUtilities.isEventDispatchThread()){
Message.popup(...);
}
else{
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
Message.popup(...);
}
});
}
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
Message.createAndShowDialog("Content", 5000); // wait 5 seconds before disposing dialog
}
});
这将确保在EDT
上创建JFrame
。另外,从您发布的代码片段来看,Message
似乎应该有一个私有构造函数。此外,既然您没有进行任何自定义渲染,为什么不直接创建一个JFrame
成员变量而不是扩展类呢?--对我来说似乎有点多余
无论如何,您也不应该在EDT
中sleep
,因为这将使GUI显示为“冻结”,并阻止其他排队事件的执行。执行长时间运行的任务时,请使用或,如@Riduidel所述。但是,如果您喜欢使用,请使用如上所示的实用程序类将Runnable
任务发布到EventQueue
上,以便在EDT
中执行
编辑
下面是我要做的(是的,它是有效的)
无论在何处调用createAndShowDialog(…)
,请执行以下操作
if(SwingUtilities.isEventDispatchThread()){
Message.popup(...);
}
else{
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
Message.popup(...);
}
});
}
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
Message.createAndShowDialog("Content", 5000); // wait 5 seconds before disposing dialog
}
});
永远不要使用update()方法或getGraphics()方法
调用update()用于AWT NOT Swing
如果您需要进行自定义绘制,则可以覆盖组件的paintComponent()方法,该方法已经可以访问图形对象。@mre我现在意识到我对Swing一无所知;-)非常感谢所有关于这个问题的信息@奥塔鲁斯,如果你还有麻烦,请告诉我!:)@我还是有麻烦。我照你说的做了,包括计时器,但有时候,它还是不显示。如果有助于理解,当我最小化/还原帧时,显示的文本将消失。您的If(SwingUtilities.isEventDispatchThread())今天为我节省了大量时间@StephaneGrenier,很高兴听到!:)“.有时JFrame是空的”什么JFrame?为了更快地获得更好的帮助,请发布一篇文章(在你研究的数百万个线程中可能已经提到过几千次)。@Andrew对此表示抱歉,我更新了代码,现在它扩展了JDialog而不是JFrame。我的错!已经做出了改变。