使用长过程从另一个 JFrame 构建 JFrame
Build JFrame from another JFrame with long process
我对 JAVA 很陌生,我有一个问题(希望我的英语不会太差)。
这是我的过程:
- 使用 JButton 在 Main 中打开第一个 JFrame(打开第二个
JFrame).
- 单击时,使用 ActionLister,我调用进程打开我的第二个
window,黑色背景(效果很好)。
但是,如果我在我的第二个 JFrame setVisible() 之后添加一个长进程(在我的代码中,只是一个 sleep(5000)),这个进程将显示为白色,并等待 sleep(5000) 到在变黑之前结束。
问题:
- 有人能告诉我为什么第二个 JFrames 显示白色直到
过程结束?也许我在构建 JFrame 时出错了
?
- 谁能告诉我如何在进程结束前将我的第二个 JFrame 显示为黑色?
找了半天,发现如果我的第二个window是直接在主线程中构建的,即使在进程结束前休眠也可以。
但是当我在另一个线程中时(比如当我点击按钮时),效果不佳!
第二部分:
点击第一个 window 按钮:
第二个 window 出现(黑色背景为空)。然后,启动结果的计算。
计算结果不能用20秒,每5秒找1个元素。
每次找到一个元素时,我希望它显示在第二个 window.
为此,我在 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秒在一个列表中添加一个元素,然后通知观察者(我的第二个window),然后观察者添加一个元素:
public void refresh(Observable o) {
_otherwindow.addResultElement(_result.getLastElement());
}
- 我得到的行为:
结果计算良好,最后第二个 window 看起来不错,有 5 个元素。但是在搜索结果期间,我的第二个 windows 仍然是空的和白色的。 . .
- 我重复一下目标:
每次在结果中添加一个元素时,我想在我的第二个 window.
中显示它
您在 Swing 事件线程上调用长进程,这将占用线程,阻止它执行重要工作,包括绘制新的 JFrame。
规范的解决方案是为您的长进程使用后台线程,而对于 Swing GUI,您会希望使用 SwingWorker——如果后台进程需要与 GUI 通信(通常是这种情况) ).
关于这个问题的详细信息和解决方案,请查看: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<Void, String>
处理传入 JList<String>
的字符串
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);
}
}
//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);
}
});
它也可能有效。
我对 JAVA 很陌生,我有一个问题(希望我的英语不会太差)。
这是我的过程:
- 使用 JButton 在 Main 中打开第一个 JFrame(打开第二个 JFrame).
- 单击时,使用 ActionLister,我调用进程打开我的第二个 window,黑色背景(效果很好)。
但是,如果我在我的第二个 JFrame setVisible() 之后添加一个长进程(在我的代码中,只是一个 sleep(5000)),这个进程将显示为白色,并等待 sleep(5000) 到在变黑之前结束。
问题:
- 有人能告诉我为什么第二个 JFrames 显示白色直到 过程结束?也许我在构建 JFrame 时出错了 ?
- 谁能告诉我如何在进程结束前将我的第二个 JFrame 显示为黑色?
找了半天,发现如果我的第二个window是直接在主线程中构建的,即使在进程结束前休眠也可以。
但是当我在另一个线程中时(比如当我点击按钮时),效果不佳!
第二部分:
点击第一个 window 按钮: 第二个 window 出现(黑色背景为空)。然后,启动结果的计算。 计算结果不能用20秒,每5秒找1个元素。 每次找到一个元素时,我希望它显示在第二个 window.
为此,我在 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秒在一个列表中添加一个元素,然后通知观察者(我的第二个window),然后观察者添加一个元素:
public void refresh(Observable o) {
_otherwindow.addResultElement(_result.getLastElement());
}
- 我得到的行为:
结果计算良好,最后第二个 window 看起来不错,有 5 个元素。但是在搜索结果期间,我的第二个 windows 仍然是空的和白色的。 . .
- 我重复一下目标: 每次在结果中添加一个元素时,我想在我的第二个 window. 中显示它
您在 Swing 事件线程上调用长进程,这将占用线程,阻止它执行重要工作,包括绘制新的 JFrame。
规范的解决方案是为您的长进程使用后台线程,而对于 Swing GUI,您会希望使用 SwingWorker——如果后台进程需要与 GUI 通信(通常是这种情况) ).
关于这个问题的详细信息和解决方案,请查看: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<Void, String>
JList<String>
的字符串
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);
}
}
//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);
}
});
它也可能有效。