2015-01-04 2 views
0

Я делаю программу, которая читает из файла, идентифицирует общие «сообщения» в файле и делает сводку этих данных. Моя проблема заключается в том, что GUI-событие, которое позволяет пользователю указывать имя и срок поиска сообщения, не прерывает работу программы, как я этого хочу.Блокировка main-thread после gui-event

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

EDIT: удалены codedump и добавил что-то resembeling в SSCCE:

class SSCCE{ 
public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable(){ 
     @Override 
     public void run(){ 
      new Gui(); 
     } 
    }); 
} 
} 

class Gui implements ActionListener{ 

boolean runn=true; 
JFrame wind2; 
JTextField nameF, searchtermF; 
JButton done; 

Gui(){ 
    runEx(); 
} 

public void runEx(){ 

    int i =0; 
    while(runn){ 
     if(i==10) break; 
     System.out.println("Open window and record information given! One at the time!!!"); 
     System.out.println(" "); 
     giveName("test"); 

     i++; 
    } 
} 

public void giveName(String s){ 


    JLabel nameL = new JLabel("Give this post a name:"); 
    JLabel searchL = new JLabel("What do you want the searchterm to be?"); 

    wind2 = new JFrame("EazyMoney"); 
    wind2.setLayout(new BorderLayout()); 

    JPanel all = new JPanel(); 
    all.setLayout(new GridLayout(2,2)); 


    searchtermF = new JTextField(30); 
    nameF=new JTextField(30); 

    all.add(nameL); 
    all.add(nameF); 
    all.add(searchL); 
    all.add(searchtermF); 

    done = new JButton("Press when you have filled in the information!"); 
    done.addActionListener(this); 

    String prn = "The post in question: " + s; 
    JLabel header = new JLabel(prn); 

    wind2.add(header, BorderLayout.NORTH); 
    all.setVisible(true); 
    wind2.add(all, BorderLayout.CENTER); 
    wind2.add(done, BorderLayout.SOUTH); 

    wind2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    wind2.pack(); 
    wind2.setLocationRelativeTo(null); 
    wind2.validate(); 
    wind2.setVisible(true); 
} 

public void actionPerformed(ActionEvent e){ 
    System.out.println("Action recorded, new window can now be shown. All information stored."); 
    System.out.println(" "); 
} 
} 

Растворы я пытался это:

  • Простой блок, что делает while(true){} и устанавливает переменную истинным после был вызван первый экземпляр g.giveName(). Я использовал ActionListener для вызова метода, который затем снова изменил переменную на false, когда был дан необходимый ввод. Это привело к серой коробке, в которой ничего нет.
  • Создание циклического барьера, который сделал то же, что и блок выше. Используется отдельный поток для вызова g.giveName(), а затем вызывается await() из прослушивателя действий. Тот же результат, что и выше.
  • Выполнение readFile выполняется отдельной веткой и вызывает invokeAndWait() на функции g.giveName(). Дал cannot call invokeAndWait() from the EDT-thread, хотя он был запущен из новой темы.

Я не могу привести примеры кода, используемого в примерах выше, поскольку я пробовал много разных решений и больше не имею его. Пожалуйста, примите во внимание, что он может быть реализован неправильно и, следовательно, может быть верным ответом на мой вопрос, хотя я не мог заставить его работать!

Конечная нота: все работы можно найти здесь, если вы хотите проверить код: https://github.com/Robiq/EazyMoneyWork

+1

Священный кодекс дамп Бэтмен! Это слишком много кода - слишком много. Судя по вашему описанию, он должен быть совместимым с SSCCE. Акцент в первом «S». –

+0

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

+0

Не блокируйте EDT (Thread Dispatch Thread). Когда это произойдет, GUI «замерзнет». См. [Параллелизм в Swing] (https://docs.oracle.com/javase/tutorial/uiswing/concurrency/) для получения подробной информации и исправления. –

ответ

0

Способ избежать блокировки EDT, если вам нужно выполнить что-то еще в том же потоке, что это временно создать новую очередь событий. Вот пример кода. В этом случае он блокирует текущий поток, ожидающий передачи какого-либо другого события, но вы можете заменить его каким бы ни требовался длительный процесс.

Сначала проверьте, работаете ли вы на EDT: SwingUtilities.isEventDispatchThread. Тогда, если вы:

EventQueue tempEventQueue = new EventQueue(); 
Toolkit.getDefaultToolkit().getSystemEventQueue().push(tempEventQueue); 
try { 
    wait(); 
} catch (InterruptedException ex) { 
    // stop waiting on interrupt 
} finally { 
    tempEventQueue.pop(); 
} 

Нечто похожее на то, как модальные диалоги работают в Swing. Однако в целом это не очень хорошая практика. Намного лучше понять, какие события нужно слушать для выполнения определенных действий. В вашем случае пользовательское событие не должно «останавливать» вашу программу - оно должно отключать неподходящие компоненты, пока пользователь не ответит, а затем снова включит их.

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