【问题标题】:Good way to set/refresh information with thread in java swing app在 java swing 应用程序中使用线程设置/刷新信息的好方法
【发布时间】:2011-12-18 22:32:49
【问题描述】:

我不是 Java 程序员,我不确定我所做的是否正确,或者是否存在更好的方法来做到这一点。

我正在制作一个多线程的 Swing Java 应用程序。
我有许多摆动组件(文本字段、texarea、标签、列表...),它们通过许多线程进行设置和刷新。

对于我的所有组件,我使用类似下面的代码(这只是一个小例子)来设置/刷新它。

Main.mainUI.setThumbLbl(image); 设置/刷新我的组件是不是一个好方法? (我在所有组件的其他线程中使用类似的东西)
还有其他更好的方法吗?

主要:

public class Main {

  public static MyMainUI mainUI;

  public static void main(String args[]) {
    mainUI = new mainUI();
    java.awt.EventQueue.invokeLater(new Runnable() {

      @Override
      public void run() {        
        mainUI.setVisible(true);
      }
    });
  }
}

Jframe:

public class MyMainUI extends JFrame {

  private JLabel thumbLbl;
  private JButton thumbBtn;

  public MyMainUI(){
    // add thumbLbl, thumBtn
    ...
    thumBtn.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseReleased(MouseEvent evt) {
        new MyThread().start();
      }
    });
  }

  public void setThumbLbl(final Image image) {
    SwingUtilities.invokeLater(new Thread() {

      @Override
      public void run() {
        thumbLbl.setIcon(new ImageIcon(image.getScaledInstance(thumbLblDim.width,
           thumbLblDim.height, Image.SCALE_DEFAULT)));
      }
    });
  }
}

线程:

public class MyThread extends Thread {
  @Override
  public void run() {
    //Get image from web server
    ...
    Main.mainUI.setThumbLbl(image);
  }
}

注意:我很快就在文本编辑器中编写了这个示例代码,可能有一些错误,但这不是我想要的 ^^。
NB2:对不起我的英语不好。

【问题讨论】:

  • 我自己,我通常使用 SwingWorker 来完成这样的事情。除了在后台线程上做事之外,它还有许多其他优点,包括因为它是一个 Future,它可以返回一个值,并且它允许轻松使用 PropertyChangeListeners。
  • 感谢您的评论,我不知道 SwingWorker,它似乎是一个不错的选择。我会试试的。
  • 另外:1) 你的英语很好。 2) 不要使用 MouseListener 来响应 JButton 按下,而是使用 ActionListener——这就是它的用途。有一些细微但重要的区别,一个重要的区别是,如果 JButton 已被禁用,MouseListener 仍会响应,而 ActionListener 将(正确)不响应。
  • 1)谢谢谷歌翻译(这是一个笑话),2)我想知道为什么在某些情况下当我的按钮被禁用时,listerner 正在工作,我想我有很多这样的错误我的代码,它将是开源的,这就是我不想犯大错的原因,我感谢你的 cmets,我希望当我发布我的应用程序时,像你这样的人会告诉我哪里出了问题。
  • 我会尝试你所说的一切并重新制作我的例子并解决这个问题

标签: java swing thread-safety swingworker concurrency


【解决方案1】:

我的意思的一个例子是这样的:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutionException;

import javax.imageio.ImageIO;
import javax.swing.*;

public class Main {
   private static void createAndShowGui() {
      JFrame frame = new JFrame("Main");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new MyMainUI());
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
 }

@SuppressWarnings("serial")
class MyMainUI extends JPanel {
   public static final String IMG_URL_PATH = "http://duke.kenai.com/Oracle/OracleStrat.png";
   private static final int PREF_W = 900;
   private static final int PREF_H = 650; 
   private JLabel thumbLbl = new JLabel();
   private JButton thumbBtn = new JButton("Get Image");

   public MyMainUI() {      
      thumbBtn.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent arg0) {
            thumbBtn.setEnabled(false);
            final ImageDownloader imgDownLoader = new ImageDownloader(IMG_URL_PATH);
            imgDownLoader.execute();

            imgDownLoader.addPropertyChangeListener(new ImgDownLoaderListener(imgDownLoader));
         }
      });

      JPanel btnPanel = new JPanel();
      btnPanel.add(thumbBtn);

      setLayout(new BorderLayout());
      add(new JScrollPane(thumbLbl), BorderLayout.CENTER);
      add(btnPanel, BorderLayout.PAGE_END);
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private class ImgDownLoaderListener implements PropertyChangeListener {
      ImageDownloader imgDownLoader;

      public ImgDownLoaderListener(ImageDownloader imgDownLoader) {
         this.imgDownLoader = imgDownLoader;
      }

      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         // swing worker is done
         if (evt.getNewValue().equals(SwingWorker.StateValue.DONE)) {
            thumbBtn.setEnabled(true);
            try {
               ImageIcon icon = imgDownLoader.get();
               if (icon != null) {
                  thumbLbl.setIcon(icon);
               }
            } catch (InterruptedException e) {
               e.printStackTrace();
            } catch (ExecutionException e) {
               e.printStackTrace();
            }
         }
      }
   }
}



class ImageDownloader extends SwingWorker<ImageIcon, Void> {
   private String imageUrlPath;

   public ImageDownloader(String imageUrlPath) {
      this.imageUrlPath = imageUrlPath;
   }

   @Override
   protected ImageIcon doInBackground() throws Exception {
      try {
         URL imgUrl = new URL(imageUrlPath);
         BufferedImage img = ImageIO.read(imgUrl);
         return new ImageIcon(img); // return the ImageIcon
      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
      return null; // or return null if an error occurs
   }

}

此示例中的后台工作线程不了解 GUI 的结构。它所做的只是下载一个图像——就是这样,然后使用 PropertyChangeListener 侦听完成的 GUI 通过在工作线程上调用 get() 来获取图像,并决定它想用它做什么。

【讨论】:

  • 谢谢你的例子,即使我认为,我可以自己做
猜你喜欢
  • 1970-01-01
  • 2010-09-25
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 2015-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多