1

私はJavaをいじっていて、アドレスにpingを実行して「ms」を出力するプログラムを作成しようとしていました。

私はJButtonを持っています:

JButton start = new JButton("START");
    start.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){

            try {
                doCommand();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        }
    });

doCommand() メソッドは次のようになります。

public static void doCommand() throws IOException{
    String s = null;
    ProcessBuilder pb = new ProcessBuilder(commands); //definiramo procesBuilder
    Process proces = pb.start(); //zaženemo proces (vrne Process)

    BufferedReader stdInput = new BufferedReader(new InputStreamReader(proces.getInputStream()));   //Branje outputa procesa
    BufferedReader stdError = new BufferedReader(new InputStreamReader(proces.getErrorStream()));   //Branje error outputa

    while((s = stdInput.readLine()) != null){   //dokler output obstaja (ni error)
        int dvop = s.indexOf(":") + 16;
        if(s.startsWith("Reply")){
            s=s.substring(dvop);
            int pres = s.indexOf(" ");
            s=s.substring(0,pres-2);
            //System.out.println(s);
            label.setText(s);
        }
    }
    while((s = stdError.readLine()) != null){   //dokler error obstaja
        System.out.println(s);
    }

}

何が起こるかというと、ボタンを押すたびにプログラムがフリーズして何も起こらず、「通常の」方法で閉じることさえできません...私は何か間違ったことをしていると思います...

4

3 に答える 3

3

StinePikeの回答の詳細。彼の言うとおり、actionPerformed() メソッドはメインの GUI イベント スレッドで実行されます。つまり、GUI は actionPerformed() が返されたときにのみ応答する可能性があります。投稿したコードは、迅速に完了しない可能性があるブロッキング I/O を使用しています。

特にこの行:

while((s = stdInput.readLine()) != null){

標準入力からの入力をブロックするもの。このブロックが有効になっている間、メソッド actionPerformed() がまだ戻っていないため、GUI は応答しなくなります。

このコードの目的は外部アプリケーションからの応答を返すことだとおっしゃっていたので、外部アプリケーションが stderr で何かを返したか、別の条件でブロックしている可能性があります。

考えられる解決策は次のとおりです。

doCommand() メソッド:

public static void doCommand() throws IOException{
    String s = null;
    ProcessBuilder pb = new ProcessBuilder(commands); //definiramo procesBuilder
    Process proces = pb.start(); //zaženemo proces (vrne Process)

    final BufferedReader stdInput = new BufferedReader(new InputStreamReader(proces.getInputStream()));   //Branje outputa procesa
    final BufferedReader stdError = new BufferedReader(new InputStreamReader(proces.getErrorStream()));   //Branje error outputa

    Thread readStdIn = new Thread(new Runnable(){
        public void run(){
            try{
                while((s = stdInput.readLine()) != null){   //dokler output obstaja (ni error)
                    int dvop = s.indexOf(":") + 16;
                    if(s.startsWith("Reply")){
                        s=s.substring(dvop);
                        int pres = s.indexOf(" ");
                        s=s.substring(0,pres-2);
                        //System.out.println(s);

                        //Execute on the main AWT thread (I'm assuming 'label' is the name of one of your GUI components)
                        SwingUtilities.invokeLater(new Runnable(){
                            public void run(){
                                label.setText(s);
                            }
                        });
                    }
                }
            }catch(IOException ex){
                //Handle This
            }
        }
    });

    Thread readStdErr = new Thread(new Runnable(){
        public void run(){
            try{
                while((s = stdError.readLine()) != null){   //dokler error obstaja
                    System.out.println(s);
                }
            catch(IOException ex){
                //Handle This Too
            }
        };
    });

    readStdIn.start();
    readStdErr.start();
}

上記のコードは、stdin と stderr の内容を読み取り、それらを個別に処理する 2 つの別個のスレッドを生成します。ブロック I/O はメインの GUI スレッドから移植されているため、外部アプリケーションが異常な動作 (フリーズやデッドロックなど) を行っても、GUI は引き続き応答する必要があります。

注: これにより、外部アプリケーションの実行が完了していなくても、ボタンを押すことができます。

編集: BufferedReader.readLine() の不足している try-catch ブロックを追加しました

于 2013-06-21T19:20:39.950 に答える
2

actionPerformed メソッドはメインスレッドで実行されます。そのため、重いタスクを実行すると、GUI がフリーズします。別のスレッドを使用することをお勧めします。

于 2013-06-21T18:12:33.707 に答える
2

これをこのタスクに使用する必要SwingWorkerがあります。ここには、優れたチュートリアルと、File Swing Worker の例を使用した例があります。

于 2013-06-21T19:48:34.040 に答える