简体   繁体   中英

How do I show a animated GIF image using a thread

I am trying to implement an image using the method below, so that when the send action is performed, the GIF image should show within a specified time(As implemented by the threadRunner pause method).

The problem is it doesn't show. And on testing, when I disable the stop() it appears at the same time as delIveryReport Textarea which shouldn't be. How do I solve this.

 private void sendActionPerformed(java.awt.event.ActionEvent evt) {              

            threadRunner t = new threadRunner();
            String fone = "";
            SendSMS sms = new SendSMS();
            String[] arMSISDN = msisdn.split(",");
            for (int i = 0; i < arMSISDN.length; i++) {

                fone = arMSISDN[i];
                fone = fone.trim();
                try {

                    Cursor cursor = new Cursor(Cursor.WAIT_CURSOR);
                    setCursor(cursor);
                    t.pause(loading);

                    sms.sendSMS(user, pass, fone, senderIDString, msgString);


                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    Cursor normal = new Cursor(Cursor.DEFAULT_CURSOR);
                    setCursor(normal);
                    t.stop(loading);
                    deliveryReport.append(fone + ": " + sms.response + "\n");
                }

            }

    //        JOptionPane.showMessageDialog(rootPane, deliveryReport);
            deliveryReport.setVisible(true);
            jScrollPane2.setVisible(true);



            redo.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
            redo.setForeground(new java.awt.Color(223, 90, 46));
            redo.setText("Would you like to send another Message?");
            yes.setEnabled(true);
            no.setEnabled(true);
            yes.setText("Yes");
            no.setText("No");
            back.setEnabled(false);
            send.setEnabled(false);


        } 

THREADRUNNER

public void pause(JLabel label){

        try {
            Thread.sleep(5000);
            label.setVisible(true);    
        } catch (InterruptedException ex) {
            Logger.getLogger(threadRunner.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void stop(JLabel l){
        l.setVisible(false);
    } 

It seems to me that your application is doing the actual work on the EDT, while your thread takes care of showing and hiding the progress label. I might be wrong, but if that is the case, then I'd recommend that you do the complete opposite of what you are doing. Updating SWING components should only be done from the EDT (Event Dispatch Thread) and no other threads.

If this is a SWING desktop application, then my recommendation would be that you take a look at SwingWorker which is a class that is specifically designed to handle long running tasks withough blocking the EDT. You could then do something like outlined below (my code might not compile 100%, but it should give you an idea of what i mean.

private void sendActionPerformed(java.awt.event.ActionEvent evt) {  
  //implement code to show progress label here
  SMSWorker w = new SMSWorker(user, pass, senderIdString, msgString, msisdn.split(","));
  w.execute();
}

public SMSWorker extends SwingWorker<Void, DeliveryReport> {

  private final String user;
  private final String pass;
  private final String senderIdString;
  private final String msgString;
  private final String[] arMSISDN;

  // this constructor runs on the current (EDT) thread.
  public SMSWorker(String user, String pass, String senderIdString, String msgString, String[] arMSISDN) {
    this.user = user;
    this.pass = pass;
    this.senderIdString = senderIdString;
    this.msgString = msgString;
    this.arMSISDN = arMSISDN;
  }

  // this function runs in a separate thread.
  public Boolean doInBackground() {

       // Instantiate SMS gateway client.
       SendSMS sms = new SendSMS();

       // Assuming a delivery report can be created like this.
       DeliveryReport deliveryReport = new DeliveryReport();

       for (int i = 0; i < arMSISDN.length; i++) {

            fone = arMSISDN[i];
            fone = fone.trim();
            try {
                sms.sendSMS(user, pass, fone, senderIDString, msgString);

            } catch (Exception e) {
                // you can notify users about exception using the publish() method.

            } finally {
                deliveryReport.append(fone + ": " + sms.response + "\n");
            }

        }

        return deliveryReport;

  }

  // this function runs on the current (EDT) thread.
  public void done() {
    try {
      // synchronize worker thread with EDT.
      DeliveryReport deliveryReport = get();
    } catch (Exception e) {
      //implement code to notify user about errors here.
    } finally {
      //implement code to hide progress label here.
    }
}

As for your question : just set the animated gif as the JLabel's icon - and SWING should take care of showing it. As long as your SMS sending code runs on another thread, SWING should happily be able to render the GIF animations without being blocked by the SMS sending code.

you have to wrap label.setVisible(true); into invokeLater();

you have remove Thread.sleep(int) from Swing code because block EDT, then you have problem with Concurency in Swing , create a new void/clas.. with Thread started from Runnable , and inside this code block you can pausing process(es) by using Thread.sleep(int) and put here label.setVisible(true); wrapped into invokeLater(); too

animations or delaing any of actions in the Swing required usage of javax.swing.Timer

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM