我有一个编译java源文件并运行它的代码。控制台输出显示在应用程序的jtextarea中。问题是,虽然正在编译源文件并且正在创建.class文件,但输出jtextarea不会显示任何内容。我尝试在不同的线程上运行冗长的任务,但这也没有帮助。我在这做错了什么?
更新:我更新了自定义输出流类的write方法,以在swing工作类中包含append方法。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
class test extends JFrame
{
JTextArea content,compiler;
JSplitPane pane;
JMenuBar jmb = new JMenuBar();
JMenu menu = new JMenu("Options");
JMenuItem item = new JMenuItem("Compile") , item1 = new JMenuItem("Run") , item2 = new JMenuItem("Save");
test()
{
setTitle("Testing Window");
setSize(700,700);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
content = new JTextArea();
compiler = new JTextArea();
PrintStream stream = new PrintStream(new cos(compiler));
System.setOut(stream);
System.setErr(stream);
pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,true,new JScrollPane(content),new JScrollPane(compiler));
pane.setResizeWeight(0.8);
add(pane);
menu.add(item);
menu.add(item1);
menu.add(item2);
jmb.add(menu);
setJMenuBar(jmb);
ActionListener listener = (ActionEvent ae) -> {
try(FileWriter file = new FileWriter("hello.java");
BufferedWriter bw = new BufferedWriter(file))
{
Scanner sc = new Scanner(content.getText());
while( sc.hasNext())
{
bw.write(sc.nextLine());
bw.newLine();
}
}catch(Exception e){e.printStackTrace();}
};
item2.addActionListener(listener);
ActionListener listener1 = (ActionEvent ae)->{
Runnable runnable = ()->{
try
{
Process p = Runtime.getRuntime().exec("javac hello.java");
p.waitFor();
System.out.print("Compiled Successfully \n");
}catch(Exception e){e.printStackTrace();}
};
Thread newThread = new Thread(runnable);
newThread.start();
};
item.addActionListener(listener1);
ActionListener listener2 = (ActionEvent ae)->{
Runnable runnable = ()->{
try
{
Process p = Runtime.getRuntime().exec("java hello");
p.waitFor();
}catch(Exception e){e.printStackTrace();}
};
Thread newThread = new Thread(runnable);
newThread.start();
};
item1.addActionListener(listener2);
setVisible(true);
}
public static void main(String args[])
{
SwingUtilities.invokeLater( ()->{new test();} );
}
}
class cos extends OutputStream
{
JTextArea textarea;
SwingWorker worker;
cos(JTextArea textarea)
{
this.textarea = textarea;
}
public void write(int b)throws IOException
{
worker = new SwingWorker()
{
protected Object doInBackground()
{
publish(String.valueOf( (char)b ));
return null;
}
protected void process(ArrayList<String> list)
{
textarea.append(list.get(list.size()-1))//to get latest string
}
};
worker.execute();
}
}
答案 0 :(得分:0)
假设您有一个简单的Java程序,它只是将一些字符串打印到控制台输出,但有一些延迟,如:
package foo1;
import java.util.concurrent.TimeUnit;
public class StringProducer {
private static final int MAX = 10;
private static final long SLEEP_TIME = 400;
public static void main(String[] args) {
System.out.println("Start");
for (int i = 0; i < MAX; i++) {
try {
TimeUnit.MILLISECONDS.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("At index: " + i);
try {
TimeUnit.MILLISECONDS.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("End");
}
}
假设您想要运行这个单独的类,并在上面的类在其自己的进程中运行时捕获操作系统的输出,并将其显示到JTextArea中,您可以在其中创建一个SwingWorker,创建一个运行操作系统命令shell程序的进程,对于Windows,"cmd.exe"
,使用扫描程序捕获进程的InputStream并在其自己的线程中“吞噬”它,然后将其发布/处理到JTextArea,如下面的代码所示。该代码假定两个Java程序都在相同的包/类路径区域中:
package foo1;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
@SuppressWarnings("serial")
public class WorkerTester extends JPanel {
private static final int ROWS = 30;
private static final int COLS = 60;
// name of the Java program to run in its own process
public static final String CLASS_TO_RUN = "StringProducer";
// our JTextArea
private JTextArea textArea = new JTextArea(ROWS, COLS);
public WorkerTester() {
// make jtextarea non-editable/focusable and put into jscrollpane
textArea.setFocusable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
// this button will start the process and the worker
JPanel btnPanel = new JPanel();
btnPanel.add(new JButton(new WorkerAction("Start Action")));
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
}
// Our JButton's Action
private class WorkerAction extends AbstractAction {
public WorkerAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
final MyWorker myWorker = new MyWorker();
myWorker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
// you always want to check for exceptions by calling
// get on the worker when done
try {
myWorker.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
});
myWorker.execute(); // run the worker
}
}
private class MyWorker extends SwingWorker<Void, String> {
private PrintStream out;
private Scanner scanner;
@Override
protected Void doInBackground() throws Exception {
@SuppressWarnings("unused")
String separator = System.getProperty("file.separator"); // in case needed
String classpath = "\"" + System.getProperty("java.class.path") + "\"";
Package packageValue = WorkerTester.this.getClass().getPackage();
String packageName = packageValue.getName() + ".";
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe");
processBuilder.redirectErrorStream(true); // combine error and input streams
Process process = processBuilder.start();
InputStream is = process.getInputStream();
OutputStream os = process.getOutputStream();
out = new PrintStream(os);
scanner = new Scanner(is);
new Thread(new ScannerGobbler(scanner)).start();
out.println("dir"); // just to test out and see where we are
out.println("java -cp .;" + classpath + " " + packageName + CLASS_TO_RUN);
out.println("exit");
out.close();
int exitValue = process.waitFor();
publish("Process Exited with exitValue of: " + exitValue);
return null;
}
@Override
protected void process(List<String> chunks) {
for (String chunk : chunks) {
textArea.append(chunk + "\n");
}
}
private class ScannerGobbler implements Runnable {
private Scanner scanner;
public ScannerGobbler(Scanner scanner) {
this.scanner = scanner;
}
@Override
public void run() {
while (scanner.hasNextLine()) {
publish(scanner.nextLine());
}
if (scanner != null) {
scanner.close();
}
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("WorkerTester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new WorkerTester());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}