JtextArea不更新自己

时间:2017-01-04 17:45:05

标签: java swing concurrency

我有一个编译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();

    }
}

1 个答案:

答案 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());
    }
}