2016-08-06 2 views
0

Я пишу программу Java, которая действует как сервер и клиент. Оставляя несоответствующие биты, он имеет три класса: Главная, Сервер и Клиент. Main просто устанавливает меню и содержит основной метод. Сервер и Клиент поддерживают алгоритмы для сервера и клиента соответственно.Как назвать тяжелый алгоритм от JButton ActionListener

То, что я пытаюсь сделать, - это вызвать алгоритм из классов сервера и клиента и их графических интерфейсов в зависимости от нажатой кнопки. Код для вызова сервера в настоящее время выглядит следующим образом:

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

Проблема заключается в том, что server.run() работает непрерывно в течение достаточно долгого времени и много тяжелой работы. Это исключает GUI, который из моего понимания заключается в том, что я вызываю метод из EDT.

Как я могу назвать этот метод из основного потока? Мне нужно создать SwingWorker и оставить его там до конца server.run()?

+1

[ 'SwingWorker'] (https://docs.oracle .com/javase/tutorial/uiswing/parallelurrency/worker.html) - это один из способов; показан другой подход [здесь] (http://stackoverflow.com/a/3245805/230513). – trashgod

ответ

3

Как я могу назвать этот метод из основного потока?

Как обычно это делается в Свинге.

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); 
    } 
} 

Это ошибки из графического интерфейса пользователя, который из моего понимания происходит потому, что я вызова метода из EDT.

Да, поскольку действие инициируется событием, actionPerformed() вызывается (или включен) EDT. Я не знаю, что вы делаете в server.run(), но я полагаю, что это не должно заканчиваться на EDT.

Должен ли я создать SwingWorker и оставить его там до конца server.run()?

В этом случае я бы использовал SwingWorker или SwingUtilities. Вы можете написать ActionHandler таким образом, используя два потока, один для выполнения некоторых «тяжелых», один для создания пользовательского интерфейса:

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

Убедитесь, что ссылка на объект сервера является окончательной, а затем вызовите метод в новом потоке в методе actionPerformed.

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

Это зависит от ваших требований, если вы хотите, чтобы пользователь ничего не делать, пока сервер возвращает не хотите, то лучше всего сделать это в Busyindicator как:

public void actionPerformed(ActionEvent e) 
{ 

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

Это покажет пользователю часового стекла во время работы сервера, и пользователь блокируется от использования пользовательского интерфейса.

Или

, если вы хотите, чтобы пользовательский интерфейс, чтобы быть отзывчивым, вам нужно вызвать 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() 
      { 
      } 
     }); 
    } 
}); 

Обратите внимание, что это не полный код для прослушивателя потоков, только ради идеи.

Смежные вопросы