当前位置: 首页 > 知识库问答 >
问题:

从另一个具有长进程的JFrame构建JFrame

楚俊杰
2023-03-14

我对JAVA相当陌生,我有一个问题(我希望我的英语不是太差)。

以下是我的过程:

  • 使用JButton(打开第二个JFrame)在主服务器中打开第一个JFrame。
  • 单击时,使用ActionLister,我调用进程以打开第二个窗口,其背景为黑色(这非常有效)。

但是,如果我在setVisible()第二个JFrame之后添加一个长进程(在我的代码中,只有一个睡眠(5000)),那么这个进程将以白色显示,并在黑色之前等待睡眠(5000)结束。

问题:

  • 有人能告诉我为什么第二个JFrames在进程结束之前都是白色的吗?也许我在构建JFrame时犯了什么错误?
  • 有人能告诉我如何在进程结束前显示第二个JFrame黑色吗?

但是当我在另一个线程中(比如当我点击按钮时),那就不好用了!

第二部分:

点击第一个窗口的按钮:显示第二个窗口(黑色背景的空窗口)。然后,启动结果的calcul。计算结果不需要20秒,每5秒会找到1个元素。每次找到一个元素,我都希望它显示在第二个窗口中。

流程

这里是我的project.jar:http://dl.free.fr/b5iusstbj

这里是我的计算结果:

public void launchCalculateResult(){
    String[] tabelements = {"test1","test2", "test3", "test4", "test5"};
    for (int i=0; i < 5; i++){
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        _elementslist.add(tabelements[i]);
        notifyObservers();
    }
}
public void refresh(Observable o) {
    _otherwindow.addResultElement(_result.getLastElement());
}
    null

结果计算良好,最后第二个窗口看起来很好,有它的5个元素。但是在搜索结果的过程中,我的第二个窗口仍然是空的和白色的。..

  • 我重复目标:每次在结果中添加元素时,我都希望在第二个窗口中显示它。

共有1个答案

刘星火
2023-03-14

您正在调用Swing事件线程上的长进程,这将使线程无法执行其重要的工作,包括绘制新的JFrame。

规范的解决方案是为长进程使用后台线程,而对于Swing GUI,您希望使用SwingWorker--如果后台进程需要与GUI通信(通常是这样)。

有关此问题和解决方案的详细信息,请查看:Swing中的并发

附带问题:您通常不希望在应用程序中显示多个JFrames。为了了解这一点的重要性以及如何改进这个设计,请查看多个JFrames

例如:

import java.awt.Color;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;

import javax.swing.*;

public class SwingExample extends JPanel {
    private JButton openDialogBtn = new JButton(new OpenDialogAction("Open Dialog"));
    private JDialog dialog;
    private DialogPanel dialogPanel = new DialogPanel();

    public SwingExample() {
        setPreferredSize(new Dimension(400, 400));
        add(openDialogBtn);
    }

    private class OpenDialogAction extends AbstractAction {
        public OpenDialogAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            dialogPanel.setText("");
            if (dialog == null) {
                Window win = SwingUtilities.getWindowAncestor(SwingExample.this);
                dialog = new JDialog(win, "Dialog", ModalityType.MODELESS);
                dialog.add(dialogPanel);
                dialog.pack();
                dialog.setLocationRelativeTo(win);
            }
            new SwingWorker<Void, Integer> () {
                private final int maxI = 5;

                @Override
                protected Void doInBackground() throws Exception {
                    for (int i = 0; i < maxI; i++) {
                        publish(i);
                        Thread.sleep(1000);
                    }
                    return null;
                }

                protected void process(java.util.List<Integer> chunks) {
                    for (Integer chunk : chunks) {
                        dialogPanel.setText("Time: " + chunk);
                    }
                };

                protected void done() {
                    dialogPanel.setText("Done!");
                };
            }.execute();
            dialog.setVisible(true);
        }
    }

    private class DialogPanel extends JPanel {
        private JTextField textField = new JTextField(10);

        public DialogPanel() {
            setBackground(Color.BLACK);
            setPreferredSize(new Dimension(200, 200));
            add(textField);
        }

        public void setText(String text) {
            textField.setText(text);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        SwingExample mainPanel = new SwingExample();
        JFrame frame = new JFrame("SwingExample");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}

示例2:使用SwingWorker 处理传递到JList 中的字符串

import java.awt.Color;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class SwingExample extends JPanel {
    private JButton openDialogBtn = new JButton(new OpenDialogAction("Open Dialog"));
    private JDialog dialog;
    private DialogPanel dialogPanel = new DialogPanel();

    public SwingExample() {
        setPreferredSize(new Dimension(400, 400));
        add(openDialogBtn);
    }

    private class OpenDialogAction extends AbstractAction {
        public OpenDialogAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            dialogPanel.clearList();
            if (dialog == null) {
                Window win = SwingUtilities.getWindowAncestor(SwingExample.this);
                dialog = new JDialog(win, "Dialog", ModalityType.MODELESS);
                dialog.add(dialogPanel);
                dialog.pack();
                dialog.setLocationRelativeTo(win);
            }
            new SwingWorker<Void, String>() {
                @Override
                protected Void doInBackground() throws Exception {
                    String[] tabelements = { "test1", "test2", "test3", "test4", "test5" };
                    for (int i = 0; i < 5; i++) {
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        publish(tabelements[i]);
                    }
                    return null;
                }

                protected void process(java.util.List<String> chunks) {
                    for (String chunk : chunks) {
                        dialogPanel.addText(chunk);
                    }
                };

                protected void done() {
                    dialogPanel.addText("Done!");
                };
            }.execute();
            dialog.setVisible(true);
        }
    }

    private class DialogPanel extends JPanel {
        private DefaultListModel<String> listModel = new DefaultListModel<>();
        private JList<String> jList = new JList<>(listModel);

        public DialogPanel() {
            jList.setPrototypeCellValue("ABCDEFG HIJKLMNOP");
            jList.setVisibleRowCount(6);
            JScrollPane scrollPane = new JScrollPane(jList);
            scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

            setBackground(Color.BLACK);
            setPreferredSize(new Dimension(200, 200));
            add(scrollPane);
        }

        public void clearList() {
            listModel.clear();
        }

        public void addText(String text) {
            listModel.addElement(text);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        SwingExample mainPanel = new SwingExample();
        JFrame frame = new JFrame("SwingExample");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}
 类似资料:
  • 问题内容: 我下棋。我写了3节课。如果是游戏则为第一。(棋盘,棋子等),另外一个用于菜单。(新,打开,设置时间等按钮) 他们两个都使用JFrame。 我想将上述两个类都放在第3类中。例如,“游戏”窗口在左侧,菜单在右侧。第三类还将通过JFrame显示整个应用程序。 怎么做? 问题答案: 您不能将一个JFrame放入另一个。您在这里有几个设计选择。您可以将JFrames更改为JPanels。这可能是

  • 问题内容: 如何从另一个类中处置JFrame?我的代码在下面列出。我使用Netbeans生成表单来生成窗口。我想使用另一个类进行处理(名称为needDispose)。 NETBEANS GENERATE (重要方法是getMainFrame()) 问题答案: 这是一个如何从另一个本身就是JFrame的类中释放JFrame的示例:

  • 问题内容: 嗨,我试图将一些文本附加到同一包中另一个类的一个小问题。以下是与JFrame有关的主要类: 我包括测试变量只是为了轻松地重新创建问题,但是无论何时运行append函数,jFrame的文本区域中都不会出现任何内容。在我的方案中,我让客户端从服务器接收文本,然后将其附加到文本框中。 顺便说一句,我正在为JFrame使用IntelliJ GUI设计器。我只包含了重新创建问题所需的代码。我仍在

  • 如何从另一个类中处理?下面列出了我的代码。 处置类别: <代码>主窗口。main\u f.dispose()不起作用,因为它不是变量。你能帮助我吗?

  • 我有3个不同的JFrames。一个是一个登录页面,另一个有,第三个是主页。现在我想要的是,当我们登录时,我想在登录页面上方显示,并在完成进度到100%时,我想关闭两个框架并打开第三个,这是主页。请好心帮我完成这项工作。谢谢//这是代码部分。 }//这打开我的进度条的第二个JFrame //在Progressbar页面的下一页,我有这个代码 //现在我想要的是,在进度条完成后,我想处理登录页面和只打

  • 问题内容: 众所周知,我是一名完全的Java新手。我已经尝试过对此进行研究(通过阅读StackOverflow上的其他文章,谷歌搜索,并问一个不太喜欢Java新手的朋友),但我不知道。答案可能是明确而容易的,但我对此视而不见。我正在尝试从其他框架中放置A。 我的应用程序应该按以下方式工作: 按下框架X时有一个按钮:产生框架Y 框架Y有一个按钮,当按下时:产生框架Z 按下框架Z时有一个按钮:在放置框