JDialog Останавливает выполнение родительского JFrame

У меня есть анимационное изображение gif, которое показывает прогресс загрузки бесконечного круга внутри jDialog... Но проблема в том, что когда я загружаю этот jDialog, коды родительского кадра останавливаются.? как это сделать..вот мой код..

ProgressDialouge pbDialog = new ProgressDialouge(this);
pbDialog.setVisible(true);
pbDialog.toFront();
postPairs.add(new BasicNameValuePair("PATH","authenticateUser.idoc"));
postPairs.add(new BasicNameValuePair("user_email",email));
postPairs.add(new BasicNameValuePair("user_password",password));
JSONArray jArray = asyncService.sendRequest(postPairs);
 if(jArray != null){
            new NewJFrame().setVisible(true);

            this.setVisible(false);
  }

если я изменю ModalityType.MODELESS моего JDiaog, это не остановит выполнение кода, но также не покажет индикатор выполнения.


person Haseeb Wali    schedule 28.12.2012    source источник


Ответы (2)


По всей вероятности, у вас есть проблема с потоками, когда вы запускаете длительную задачу в потоке событий Swing, не позволяя потоку событий обновлять графический интерфейс. Решение состоит в использовании фонового потока, например, предоставляемого SwingWorker.

Я предполагаю, что оскорбительная строка:

JSONArray jArray = asyncService.sendRequest(postPairs);

Итак, еще раз, сделайте это в фоновом потоке. Чтобы узнать больше об этом, перейдите по этой ссылке: Параллелизм в Swing

Например:

import java.awt.Point;
import java.awt.Window;
import java.awt.event.ActionEvent;

import javax.swing.*;

public class ShowSwingWorker {
   private JPanel mainPanel = new JPanel();
   private JButton myBtn = null;
   private ProgressDialouge pbDialog = null;

   public ShowSwingWorker() {
      myBtn = new JButton(new AbstractAction("Push Me") {

         @Override
         public void actionPerformed(ActionEvent evt) {
            JButton source = (JButton) evt.getSource();
            source.setEnabled(false); // disable button
            Window win = SwingUtilities.getWindowAncestor(source);
            new MySwingWorker().execute(); // start background thread

            if (pbDialog == null) {
               pbDialog = new ProgressDialouge(win);               
               pbDialog.pack();
               pbDialog.setLocationRelativeTo(win);
               Point loc = pbDialog.getLocation();
               pbDialog.setLocation(loc.x - 100, loc.y - 100);
            }
            pbDialog.setVisible(true);
            // pbDialog.toFront();
         }
      });

      mainPanel.add(myBtn);
   }

   public JComponent getMainPanel() {
      return mainPanel;
   }

   private class MySwingWorker extends SwingWorker<Void, Void> {
      @Override
      protected Void doInBackground() throws Exception {
         Thread.sleep(4000); // emulate a long-running task

         // postPairs.add(new BasicNameValuePair("PATH",
         // "authenticateUser.idoc"));
         // postPairs.add(new BasicNameValuePair("user_email", email));
         // postPairs.add(new BasicNameValuePair("user_password", password));
         // JSONArray jArray = asyncService.sendRequest(postPairs);
         // if (jArray != null) {
         // new NewJFrame().setVisible(true);
         //
         // this.setVisible(false);
         // }
         return null;
      }

      @Override
      protected void done() {
         // Here you change your display.
         // you were swapping JFrames, but I recommend that you instead change views.
         myBtn.setEnabled(true);
         pbDialog.setVisible(false);
      }
   }

   private class ProgressDialouge extends JDialog {

      public ProgressDialouge(Window win) {
         super(win, "MyDialog", ModalityType.APPLICATION_MODAL);
         JProgressBar pBar = new JProgressBar();
         pBar.setIndeterminate(true);
         add(pBar);
      }

   }

   private static void createAndShowGUI() {
      ShowSwingWorker paintEg = new ShowSwingWorker();

      JFrame frame = new JFrame("ShowSwingWorker");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(paintEg.getMainPanel());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGUI();
         }
      });
   }
}
person Hovercraft Full Of Eels    schedule 28.12.2012
comment
я делаю индикатор выполнения видимым после строки, на которую вы указываете ... но после того, как индикатор выполнения отображается, мои следующие строки не выполняются. - person Haseeb Wali; 28.12.2012
comment
@HaseebWali: я сказал вам, что вам нужно сделать - вам нужно использовать фоновый поток. Пожалуйста, попробуйте. - person Hovercraft Full Of Eels; 28.12.2012
comment
@HaseebWali: если вы хотите, чтобы ваш диалог был модальным, тогда весь соответствующий код, который вы хотите запустить, необходимо будет вызывать до вызова setVisible(true) в диалоговом окне. - person Hovercraft Full Of Eels; 28.12.2012

Строка pbDialog.setVisible(true) будет блокироваться до тех пор, пока диалог не будет закрыт в случае модального диалога. Если вы хотите, чтобы диалог открывался без блокировки, вы должны сделать его немодальным. Что бы ни мешало вашей анимации работать, вероятно, это связано с написанием синхронного кода для перерисовки диалогового окна. Вам необходимо использовать EventQueue для периодической перерисовки кадров. Вы можете использовать отдельный поток или использовать более простой код, который не требует такого потока:

public void paintComponent(Graphics g) {
    if( animate ) {
       Graphics2D g2d = (Graphics2D)g;
       BufferedImage frame = frames[currentFrame];
       g2d.drawImage(frame, null, x, y);
       frame.draw( g );
       currentFrame = (currentFrame + 1) % frames.length;
       repaint(); // this call will schedule a repaint at some point later.
    }
}

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

http://docs.oracle.com/javase/6/docs/api/java/awt/Graphics2D.html#drawImage(java.awt.Image, java.awt.geom.AffineTransform, java.awt.image.ImageObserver)

Для выполнения анимации в таких вещах, как анимированные GIF-файлы.

person chubbsondubs    schedule 28.12.2012
comment
1) Его диалог уже немодальный диалог. 2) Почему вы рекомендуете ему вызывать repaint() из метода paintComponent? Этого делать не следует. Пожалуйста, исправьте это в ближайшее время. - person Hovercraft Full Of Eels; 28.12.2012
comment
1) Кажется, он не понимает разницы между модальным и немодальным и почему это работает именно так. Я хотел дать понять, что ему нужен немодальный. 2) Нет ничего плохого в вызове перерисовки в Paint, если вы хотите перерисовать компонент. Это экономит использование потока только для того, чтобы делать то же самое (т.е. вызывать repaint()). Вам не нужен поток, посвященный вызову repaint(). Repaint запланирует что-то в EventQueue для перерисовки компонента. - person chubbsondubs; 28.12.2012
comment
Стоимость использования Thread или Swing Timer минимальна, а с помощью Thread или Timer вы можете контролировать скорость и управлять остановкой или остановкой анимации. Основное правило, которому нужно следовать, заключается в том, что paint и paintComponent должны использоваться только для рисования и рисования. Его никогда не следует использовать для логики программы, для установки состояния графического интерфейса или для анимации. - person Hovercraft Full Of Eels; 28.12.2012