JDialog行为不当 [英] JDialog misbehaviour

查看:236
本文介绍了JDialog行为不当的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  JDialog dialog = new JDialog(parent JFrame,blabla); 
dialog.setLayout(new BorderLayout());

JLabel label = new JLabel(more blabla);

dialog.getContentPane()。add(label,BorderLayout.CENTER);

dialog.setSize(new Dimension(280,80));
dialog.setLocationRelativeTo(parent JFrame);
dialog.setVisible(true);

//需要时间执行的代码的一部分
//实际上,我在这里发送电子邮件,但它并不重要我做什么,
/ /如你将阅读下面

dialog.dispose();

我有上面的代码,它的用途是在执行某些代码时向用户显示一条消息(执行代码大约需要5-10秒,我不希望用户认为程序冻结)。



问题是,JLabel被添加到对话框没有出现。



但是,如果我将JDialog设置为modal(添加true作为上面的最后一个参数构造函数),它会出现,但然后我想要被执行的代码将不会运行,直到对话框被关闭,违反它的目的。



执行并不重要,因为它在代码中的位置,我试图离开它,因为它目前在上面 - 没有执行代码 - 对话框将显示分裂秒,但我可以看到它是空的。 p>

我知道我可以创建一个配置窗口,并说待机10秒,代码正在执行,但我不想这样做。



我也试过为JFrame swaping JDialog,文本仍然不会出现。



我缺少什么?

解决方案

如果长时间运行的任务在 Event Dispatch Thread 对话框可能没有机会绘制/重绘本身,直到任务完成。有关EDT的详细信息,请查看并发度摆动教程。



下面是一个使用您的代码并演示错误对话框的示例:

  import java.awt.BorderLayout; 
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class TestDialog {

private static void createAndShowGUI(){
final JFrame frame = new JFrame(Demo);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JButton button = new JButton(Execute);
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
final JDialog dialog = new JDialog((JFrame)frame,blabla );
dialog.setLayout(new BorderLayout());
JLabel label = new JLabel(more blabla);
dialog.getContentPane()。add(label,BorderLayout.CENTER) ;

dialog.setSize(new Dimension(280,80));
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);

try {
Thread.sleep(3000);
} catch(InterruptedException ex){
ex.printStackTrace();
}

.setVisible(false);
dialog.dispose();
}

});

frame.add(button);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

public static void main(String [] args){
javax.swing.SwingUtilities.invokeLater(new Runnable(){
public void run {
createAndShowGUI();
}
});
}
}

考虑重构您的实现,执行长时间运行的任务工作线程。例如,您可以使用 SwingWorker 完成此操作。



这是一个演示,演示与简单的工人相同的对话框:

  import java.awt.BorderLayout; 
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

public class TestDialogWithWorker {

private static void createAndShowGUI(){
final JFrame frame = new JFrame(Demo);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JButton button = new JButton(Execute);
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
new Worker(frame).execute();
}

});

frame.add(button);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

static class Worker extends SwingWorker< Void,Void> {
JDialog对话框;

public Worker(JFrame parent){
dialog = new JDialog((JFrame)parent,blabla);
dialog.setLayout(new BorderLayout());
JLabel label = new JLabel(more blabla);
dialog.getContentPane()。add(label,BorderLayout.CENTER);

dialog.setSize(new Dimension(280,80));
dialog.setLocationRelativeTo(parent);
dialog.setVisible(true);
}

@Override
protected Void doInBackground()throws Exception {
Thread.sleep(3000);
return null;
}

@Override
protected void done(){
dialog.setVisible(false);
dialog.dispose();

try {
get();
} catch(Exception e){
e.printStackTrace();
}
}
}

public static void main(String [] args){
javax.swing.SwingUtilities.invokeLater(new Runnable {
public void run(){
createAndShowGUI();
}
});
}
}


JDialog dialog = new JDialog(parent JFrame, "blabla");
dialog.setLayout(new BorderLayout());

JLabel label = new JLabel("more blabla");

dialog.getContentPane().add(label, BorderLayout.CENTER);

dialog.setSize(new Dimension(280, 80));
dialog.setLocationRelativeTo(parent JFrame);
dialog.setVisible(true);

//part of code that takes time to execute
//actually, I'm sending an email here, but it doesn't really matter what I do,
//as you will read below        

dialog.dispose();

I have the code above and it's use is to display a message to the user while some code is executing (execution of code takes about 5-10 seconds, I don't want user to think the program froze).

The problem is, JLabel that was added to the dialog doesn't appear at all. Whatever I add to the dialog, it doesn't appear, to be exact.

However, if I set JDialog to modal (add true as the last argument to the above constructor), it would appear, but then the code I wanted to be executed wouldn't run until the dialog was closed, defying it's purpose.

The code that would be executing doesn't really matter due to it's position in the code, and I tried leaving it as it's currently above - with no executing code at all - the dialog would show up for split second, but I could saw it was empty.

I know I could create a conformation window and say "standby for 10 seconds, code is executing", but I don't want to do it that way.

I also tried swaping JDialog for JFrame, text still wouldn't appear.

What am I missing?

解决方案

If the long running task is executed on Event Dispatch Thread (EDT) then the dialog may not have a chance to paint/repaint itself until the task is finished. Check out Concurrency in Swing tutorial for more details on EDT.

Here is a sample that utilizes your code and it demonstrates the misbehaved dialog :

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class TestDialog {

    private static void createAndShowGUI() {
        final JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton button = new JButton("Execute");
        button.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                final JDialog dialog = new JDialog((JFrame)frame, "blabla");
                dialog.setLayout(new BorderLayout());
                JLabel label = new JLabel("more blabla");
                dialog.getContentPane().add(label, BorderLayout.CENTER);

                dialog.setSize(new Dimension(280, 80));
                dialog.setLocationRelativeTo(frame);
                dialog.setVisible(true);

                try {
                    Thread.sleep(3000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }

                dialog.setVisible(false);
                dialog.dispose();
            }

        });

        frame.add(button);          
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

Consider refactoring your implementation by executing the long running task on a worker thread. For example you can accomplish that with use of SwingWorker.

Here is a demo that illustrates the same dialog with a simple worker:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

public class TestDialogWithWorker {

    private static void createAndShowGUI() {
        final JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton button = new JButton("Execute");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Worker(frame).execute();
            }

        });

        frame.add(button);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    static class Worker extends SwingWorker<Void, Void> {
        JDialog dialog;

        public Worker(JFrame parent) {
            dialog = new JDialog((JFrame) parent, "blabla");
            dialog.setLayout(new BorderLayout());
            JLabel label = new JLabel("more blabla");
            dialog.getContentPane().add(label, BorderLayout.CENTER);

            dialog.setSize(new Dimension(280, 80));
            dialog.setLocationRelativeTo(parent);
            dialog.setVisible(true);
        }

        @Override
        protected Void doInBackground() throws Exception {
            Thread.sleep(3000);
            return null;
        }

        @Override
        protected void done() {
            dialog.setVisible(false);
            dialog.dispose();

            try {
                get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }       
}

这篇关于JDialog行为不当的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆