Приоритет работы в Java.(Объект создается и запускается до обновления графического интерфейса?) - PullRequest
6 голосов
/ 24 июля 2011

Я хочу, чтобы графический интерфейс пользователя изменил заголовок кнопки с «Перейти» на «Работающий ...», прежде чем объект будет создан и фактически выполнит свою работу. По окончании я хочу, чтобы заголовок кнопки снова переключился на «Перейти».

Вот код:

    private class convert implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        JButton button = (JButton)e.getSource();

        button.setText("Working...");
        button.setEnabled(false);

        anObject name = new AnObject();
        boolean result = name.methodName(chooser.getSelectedFile(),encoding);

        // A bunch of stuff was here but irrelevant to the question,
        // so it was removed to save room.

        button.setEnabled(true);
        button.setText("Go");
    }

На самом деле на практике происходит имя , вызывается methodName , и ТОГДА кнопка обновляется на экране, несмотря на то, что я сказал ВМ изменить сначала название кнопки.

Моя рабочая теория заключается в том, что, учитывая, что я не сделал эту программу многопоточной, это связано с приоритетом работы, внутренним потоком JVM или чем-то ...

Есть предложения?

Ответы [ 3 ]

11 голосов
/ 24 июля 2011

Я знаю, что вы уже приняли решение, но, поскольку вы столкнулись с синдромом «замороженного интерфейса», у вас наверняка возникнет проблема с многопоточностью, и invokeLater не решит вашу проблему. Как уже отмечалось выше, extraneon, вам нужен SwingWorker или какой-нибудь фоновый поток для решения этой проблемы. Кроме того, я думаю, что это хороший случай для использования AbstractAction, а не ActionListener. Например:

import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class Convert extends AbstractAction {
   private static final long SLEEP_TIME = 3000; // 3 seconds
   private String enabledText;
   private String disabledText;

   public Convert(String enabledText, String disabledText) {
      super(enabledText);
      this.enabledText = enabledText;
      this.disabledText = disabledText;
   }

   public void actionPerformed(ActionEvent e) {
      Object source = e.getSource();
      if (!(source instanceof JButton)) {
         return;
      }
      final JButton button = (JButton) source;
      setButtonEnabled(button, false);
      new SwingWorker<Void, Void>() {
         @Override
         protected Void doInBackground() throws Exception {
            // TODO: long-running code goes here. 
            // Emulated by Thread.sleep(...) 
            Thread.sleep(SLEEP_TIME);
            return null;
         }

         @Override
         protected void done() {
            setButtonEnabled(button, true);
         }
      }.execute();
   }

   public void setButtonEnabled(JButton button, boolean enabled) {
      if (enabled) {
         button.setText(enabledText);
         button.setEnabled(true);
      } else {
         button.setText(disabledText);
         button.setEnabled(false);
      }
   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("Convert");
      frame.getContentPane().add(new ConvertGui());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}

@SuppressWarnings("serial")
class ConvertGui extends JPanel {
   public ConvertGui() {
      add(new JButton(new Convert("GO", "Working...")));
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(300, 200);
   }
}
7 голосов
/ 24 июля 2011

В потоке событий происходит обратный вызов «ActionPerformed», и обычно ничего в GUI не будет обновляться, пока не вернется. Если вы хотите обновить графический интерфейс, сделать что-то, а затем обновить его снова, вам нужно будет обновить графический интерфейс, создать поток и вернуться. Затем поток должен выполнить свое действие, а затем выполнить SwingUtilities.invokeLater для обновления графического интерфейса.

5 голосов
/ 24 июля 2011

Попробуйте SwingUtilities.invokeLater () .

private class convert implements ActionListener {
public void actionPerformed(ActionEvent e) {
    final JButton button = (JButton)e.getSource();

    button.setText("Working...");
    button.setEnabled(false);

    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            anObject name = new AnObject();
            boolean result = name.methodName(chooser.getSelectedFile(),encoding);

            // A bunch of stuff was here but irrelevant to the question,
            // so it was removed to save room.

            button.setEnabled(true);
            button.setText("Convert");
        }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...