【问题标题】:Build JFrame from another JFrame with long process从另一个具有长过程的 JFrame 构建 JFrame
【发布时间】:2016-11-25 18:45:29
【问题描述】:

我是 JAVA 的新手,我有一个问题(我希望我的英语不会太差)。

这是我的过程:

  • 在 Main 中打开第一个 JFrame,使用 JButton(打开第二个 JFrame)。
  • 点击时,使用 ActionLister,我调用进程打开我的第二个 窗口,黑色背景(效果很好)。

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

问题:

  • 谁能告诉我为什么第二个 JFrame 在 过程结束?也许我在构建 JFrame 时做错了什么 ?
  • 谁能告诉我如何在流程结束之前显示我的第二个 JFrame 黑色?

我找了很久,发现如果我的第二个窗口是直接在主线程中构建的,即使在进程结束前休眠也是可以的。

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

第二部分:

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

为此,我在 JFrame 的这个结果上添加了一个观察者,它会在每次找到一个元素时添加一个元素。我希望你明白。 这是我想做的图片:

Process

这是我的项目 .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();
    }
}

你可以看到它每2秒在列表中添加一个元素,然后通知观察者(我的第二个窗口),然后观察者添加一个元素:

public void refresh(Observable o) {
    _otherwindow.addResultElement(_result.getLastElement());
}
  • 我得到的行为:

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

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

【问题讨论】:

  • 使用 internalJframe 形式

标签: java jframe jbutton actionlistener


【解决方案1】:

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

规范的解决方案是为长进程使用后台线程,对于 Swing GUI,如果后台进程需要与 GUI 通信(通常是这种情况),则需要使用 SwingWorker。

关于这个问题和解决方案的详细信息,请查看:Concurrency in Swing

附带问题:您通常不希望在应用程序中显示多个 JFrame。为什么这很重要以及如何改进这个设计,请查看Multiple 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&lt;Void, String&gt; 处理传递给 JList&lt;String&gt; 的字符串

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);
    }
}

【讨论】:

  • @NewOne:不客气。如果您仍然遇到问题,请告诉我们并向我们展示更多信息。一方面,为什么绝对要求您只使用 JFrame?为什么一个窗口不能是 JDialog?接下来,请在您的问题中显示代码,而不是链接。尝试创建一个可以编译和运行的小型可运行程序,它可以直接向我们展示您的问题,minimal reproducible example(请阅读链接)。祝你好运!
  • 我还是有问题 :) (但我总是保持微笑)。我添加了一些东西,但我被放入了答案中,你能看到吗?我放了我想要建造的照片。我正在学习 JDialog 的工作原理,看看我是否可以使用它!再次感谢!
  • @NewOne:感谢您的回复。除非您发布实际答案,否则您不想发布答案。这样做可能会阻止其他人回答您的问题,因为他们已经看到了两个答案。相反,请删除该答案并使用新信息编辑您的原始问题。此外,虽然图片有点帮助,但我真正需要看到的是一个小的可运行程序,不是在链接中,而是在您的问题中作为代码格式的文本发布。再次祝你好运!
  • 好的,再次感谢DontKnowMuchBut越来越好:)我刚刚删除了我的答案,并在我的问题中添加了代码:)
  • @NewOne:再次,"...a small runnable program, not in a link, but posted as code-formatted text in your question."。链接将不起作用。将您的小型可运行代码作为代码格式的文本发布在您的问题中。这将帮助所有帮助大量的人。祝你好运!
【解决方案2】:
//Make constructor class for both JFrame then 
 //write this code into your JFrame where your button is accesing another JFrame
 //Note:- jb=button var name,
 //       jf=JFrame vatr name,
 //       addnew()=JFrame Class to be open.

  jb.addActionListener(new ActionListener() { 
    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub
        new addnew();
        jf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
       } 
   });

它也可以工作。

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2013-06-21
    • 1970-01-01
    • 2014-12-22
    • 1970-01-01
    • 2018-10-02
    • 2014-10-07
    相关资源
    最近更新 更多