2016-08-06 14 views
0

私は、サーバーとクライアントの両方として機能するJavaプログラムを作成しています。無関係のビットを残して、メイン、サーバー、クライアントという3つのクラスがあります。 Mainはメニューを設定し、mainメソッドを含んでいます。サーバーとクライアントはそれぞれサーバーとクライアントのアルゴリズムを保持します。JButton ActionListenerから重いアルゴリズムを呼び出す方法

私がしようとしているのは、押されたボタンに応じて、サーバークラスとクライアントクラスとそれらのGUIからアルゴリズムを呼び出すことです。サーバーを呼び出すコードは、現在次のようになります。

serverButton = new JButton(); 
serverButton.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
     server.showGUI(); 
     server.run(); 
    } 
}); 

問題はserver.run()はかなり長い間継続的に実行し、重い物を持ち上げるのがたくさんあるということです。これは、私がEDTからメソッドを呼び出しているので、私の理解からですGUIをバグアウト。

メインスレッドからこのメソッドを呼び出すにはどうすればよいですか? SwingWorkerを作成し、server.run()の最後までそこに置く必要がありますか?

+1

をhttps://docs.oracle .com/javase/tutorial/uiswing/concurrency/worker.html)は1つの方法です。別のアプローチが示されている[ここ](http://stackoverflow.com/a/3245805/230513)。 – trashgod

答えて

3

メインスレッドからこのメソッドを呼び出す方法はありますか。

これは通常、スイングで行われます。私はEDTからメソッドを呼び出す だから私の理解からであるGUI、アウト

public class WhatEverServer { 

    private UserInterface userInterface; 
    [...] 

    private static void createAndShowGUI() { 

     if(GraphicsEnvironment.isHeadless()) 
     logger.log(Level.FATAL, "This system seems to be 'headless'. Aborting now."); 
     else { 
     userInterface = UserInterface.getInstance(); 
     userInterface.createAndShowUI(); 
     } 
    } 

    public static void main(String[] args) { 

     // schedule a job for the event-dispatching thread: 
     // creating and showing this application's GUI. 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 
} 


public class UserInterface { 

    ... 
    public void createAndShowUI() { 

     // make sure we have nice window decorations. 
     JFrame.setDefaultLookAndFeelDecorated(true); 

     UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); 

     // create and set up the window. 
     JFrame frame = new JFrame("Whatever Server"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     // set UI components, i.e 

     // set main menu bar 
     frame.setJMenuBar(this.mainMenuBar); 

     // set layout 
     frame.getContentPane().setLayout(new BorderLayout()); 

     // add UI components 

     // display the window. 
     frame.pack(); 
     frame.setVisible(true); 
    } 
} 

このバグ。

はい、アクションはイベントによってトリガーされるため、actionPerformed()はEDTによって(または)呼び出されます。 server.run()で何をしているのか分かりませんが、EDTで終わるべきではないと思います。

server.run()の最後までSwingWorkerを作成してそこに置く必要がありますか?

この場合、私はSwingWorkerまたはSwingUtilitiesを使用します。次の2つのスレッド、「力仕事」の一部を行うための1、UIを設定するための一つを使用して、このような方法でのActionHandlerを書くことができます([ `SwingWorker`]

public void actionPerformed(ActionEvent e) { 

    new Thread(new Runnable { 
    public void run() { 
     ... 
     // do some 'heavy lifting' here ... 

     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      server.setupUI(); 
     } 
    ) 
     ... 
     // or do some 'heavy lifting' here 
    }); 
    } 
} 
0

サーバーオブジェクトの参照がfinalであることを確認してから、actionPerformedメソッドの新しいスレッドでメソッドを呼び出します。これが表示されます

public void actionPerformed(ActionEvent e) 
{ 

    BusyIndicator.showWhile(Display.getCurrent(), new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      server.run(); 
     } 
    }); 
} 

ユーザー:

Runnable task =() -> {server.run();}; 
Thread thread = new Thread(task); 
thread.start(); 
0

それはあなたのサーバーが戻るまで行うには何もしたくないユーザーをしたい場合、それはBusyindicatorのようにそれを行うのがベストです、あなたの条件に依存しますサーバーが稼動している間に砂時計が点灯し、ユーザーはUIを使用できなくなります。

それとも

あなたはUIが応答するようにしたい場合は、別のスレッドでserver.run()を呼び出す必要があります。

MyThread t = new MyThread() 
{ 
    public void run() 
    { 
     server.run(); 
    } 
} 
t.start(); 

、UIがそのことを行うことができますので、サーバの応答の完了を通知するスレッドためのリスナーを追加することをお勧めします。

t.addListener(new MyThreadListener() 
{ 
    public void serverDone() 
    { 
     Display.getDefault().asyncExec(new Runnable() 
     { 
      public void run() 
      { 
      } 
     }); 
    } 
}); 

これはスレッドリスナーの完全なコードではありません。アイデアのためです。

関連する問題