gpt4 book ai didi

java - 进程运行时在窗口中显示计时器

转载 作者:行者123 更新时间:2023-11-30 06:13:39 25 4
gpt4 key购买 nike

所以我当前正在通过以下函数执行脚本:

public static boolean executePythonScriptWithArgs(File file, String args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
Process p = Runtime.getRuntime().exec("python3 " + file.getPath() + " " + args);

BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));

// Read the output from the command
String s;
while ((s = stdInput.readLine()) != null) {
if(s.equals("success")) {
result = true;
}
}

} catch (IOException e) {
e.printStackTrace();
}
}
};

ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(r);

return result;
}

为了阻止 GUI 卡住,我创建了一个新的 Runnable 对象并执行它来检查结果是否为 true。我正在使用以下命令更改变量结果:

私有(private)静态 volatile boolean 结果 = false;

能够在可运行线程期间更改值是 volatile

但是,这只是在后台运行,我希望打开一个新窗口(如果可以的话,可能使用 JOptionPane)来仅显示计时器,然后将其关闭当达到成功值时。

我怎样才能做到这一点?

编辑:

我正在使用的代码(除了用于容纳面板的 JFrame 之外)如下所示:

MyListener.java

public class MyListener implements ActionListener
{
public static InputStream getScriptResource(String fileName) {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
InputStream is = classLoader.getResourceAsStream("scripts/" + fileName);
return is;
}

public void actionPerformed(ActionEvent e) {
if(e.getSource() == MyPanel.button) {
String options = "";

try {
File tempFile = File.createTempFile("quick", ".py");
tempFile.deleteOnExit();
// Get your script and prepare OutputStream to tempFile
// Try with resources, to close streams
try (InputStream is = getScriptResource("quick.py"); FileOutputStream out = new FileOutputStream(tempFile)) {
// Copy InputStream to OutputStream.
IOUtils.copy(is, out);
}
boolean result = ScriptExecutor.executePythonScriptWithArgs(tempFile, options);
if (result) {
JOptionPane.showMessageDialog(Client.INSTANCE, "Scan completed successfully!", "Info", JOptionPane.PLAIN_MESSAGE);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}

MyPanel.java

public class MyPanel extends JPanel
{
public static JButton button;
private ActionListener myListener;

public MyPanel() {
this.myListener = new MyListener();
setLayout(new GridLayout(1,1));

addComponents();

setVisible(true);
}

private void addComponents() {
button = new JButton("Run Script");
button.addActionListener(myListener);
add(button);
}
}

ScriptExecutor.java

public class ScriptExecutor
{
private static volatile boolean result = false;

public static boolean executePythonScriptWithArgs(File file, String args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
Process p = Runtime.getRuntime().exec("python3 " + file.getPath() + " " + args);

BufferedReader stdInput = new BufferedReader(new
InputStreamReader(p.getInputStream()));

// Read the output from the command
String s;
while ((s = stdInput.readLine()) != null) {
if(s.equals("success")) {
result = true;
}
}

} catch (IOException e) {
e.printStackTrace();
}
}
};

ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(r);

return result;
}
}

此代码可以放入任何要运行的 jframe 中 - 注意:我的环境使用 Maven,并且可以在资源文件夹中找到该脚本。

最佳答案

一种方法:在长时间运行的代码之前声明对话框窗口,但在执行线程之后显示它。然后在线程完成运行后使用回调关闭对话框。上面给出的顺序的原因是——对话框需要对回调可见,因此需要首先声明,但模式对话框会阻塞代码流,因此需要在启动后台线程后显示。

请注意,SwingWorkers 已经为您设置了回调机制,如果需要,您可以使用它。

例如:

import java.awt.BorderLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;

@SuppressWarnings("serial")
public class CallBackEgGui extends JPanel {
private Action startThreadAction = new StartThreadAction(this);
private JButton startThreadBtn = new JButton(startThreadAction);
private JTextArea textArea = new JTextArea(15, 30);
private JProgressBar progressBar = new JProgressBar();

public CallBackEgGui() {
progressBar.setIndeterminate(true);

JPanel btnPanel = new JPanel();
btnPanel.add(startThreadBtn);

textArea.setFocusable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

setLayout(new BorderLayout());
add(scrollPane);
add(btnPanel, BorderLayout.PAGE_END);
}

public void showText(String text) {
textArea.append(text + "\n");
}

public void startProcess() {
// disable the JButton
startThreadAction.setEnabled(false);

// display a JOptionPane (or any modal JDialog) that can hold anything, including a counter if we want
// would use a Swing Timer if I wanted to show a Timer
String title = "Running Python Script";
int messageType = JOptionPane.PLAIN_MESSAGE;
JOptionPane.showMessageDialog(CallBackEgGui.this, progressBar, title , messageType);
}

public void endProcess(boolean result) {
// re-enable the JButton
startThreadAction.setEnabled(true);

// one way to close the JOptionPane
Window win = SwingUtilities.getWindowAncestor(progressBar);
win.dispose();

// display another JOptionPane that shows the result of the process
String message = "Python script Success: " + result;
String title = "Return From Python Script";
int messageType = JOptionPane.PLAIN_MESSAGE;
JOptionPane.showMessageDialog(CallBackEgGui.this, message, title , messageType);
}

private static void createAndShowGui() {
CallBackEgGui mainPanel = new CallBackEgGui();

JFrame frame = new JFrame("LongRunningTimer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

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

}

@SuppressWarnings("serial")
class StartThreadAction extends AbstractAction {
private CallBackEgGui gui;
private LongRunningCode longRunningCode;

public StartThreadAction(CallBackEgGui gui) {
super("Start Long Running Code");
this.gui = gui;
}

@Override
public void actionPerformed(ActionEvent e) {
longRunningCode = new LongRunningCode(gui);
longRunningCode.execute(); // start the SwingWorker

// order is important since the method below shows the modal dialog
// and thus blocks any code flow below it. So execute the worker FIRST
// before calling this blocking code
gui.startProcess();
}
}

class LongRunningCode extends SwingWorker<Boolean, String> {
private static final int MAX = 10;
private static final long MILLI_SECONDS_SLEEP = 400;
private CallBackEgGui gui;

public LongRunningCode(CallBackEgGui gui) {
this.gui = gui;
}

@Override
protected Boolean doInBackground() throws Exception {
// this code is in place of the Python script
// done within a background thread
for (int i = 0; i < MAX; i++) {
TimeUnit.MILLISECONDS.sleep(MILLI_SECONDS_SLEEP);

// in the real program, the text will be from the InputStream from
// the Python process.
String text = "Value: " + i;
publish(text); // then send the text to the GUI
}

// occasionally returns false
boolean returnValue = Math.random() > 0.2;
return returnValue;
}

@Override
protected void process(List<String> chunks) {
// this code is called on the Swing event thread
for (String text : chunks) {
gui.showText(text); // tell GUI to display text
}
}

@Override
protected void done() {
// this code is called on the Swing event thread
try {
boolean result = get(); // get the result from the Worker thread
gui.endProcess(result); // tell GUI that process is done
} catch (InterruptedException | ExecutionException e) {
// TODO handle exception!
e.printStackTrace();
}
}
}

另请查看Lesson: Concurrency in Swing

关于java - 进程运行时在窗口中显示计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49707994/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com