在JavaSwing应用程序中使用线程设置/刷新信息的好方法

在JavaSwing应用程序中使用线程设置/刷新信息的好方法,java,swing,thread-safety,swingworker,concurrency,Java,Swing,Thread Safety,Swingworker,Concurrency,我不是Java程序员,我不确定我所做的是否正确,或者是否有更好的方法来实现这一点 我正在制作一个带有多线程的swing Java应用程序。 我有许多swing组件(textfield、texarea、label、list等),它们通过许多线程进行设置和刷新。 对于我所有的组件,我都使用下面的代码(这只是一个小例子)来设置/刷新它。 是Main.mainUI.setThumbLbl(图像)设置/刷新我的组件是否是一种好方法?(我在其他线程中对所有组件使用类似的方式) 还有其他更好的方法吗 主要内容

我不是Java程序员,我不确定我所做的是否正确,或者是否有更好的方法来实现这一点

我正在制作一个带有多线程的swing Java应用程序。
我有许多swing组件(textfield、texarea、label、list等),它们通过许多线程进行设置和刷新。

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

Main.mainUI.setThumbLbl(图像)设置/刷新我的组件是否是一种好方法?(我在其他线程中对所有组件使用类似的方式)
还有其他更好的方法吗

主要内容:

Jframe:

线程:

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

NB2:对不起,我的英语不好。

我的意思是这样的:

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
   }

}
导入java.awt.BorderLayout;
导入java.awt.Dimension;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.image.buffereImage;
导入java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入java.io.IOException;
导入java.net.MalformedURLException;
导入java.net.URL;
导入java.util.concurrent.ExecutionException;
导入javax.imageio.imageio;
导入javax.swing.*;
公共班机{
私有静态void createAndShowGui(){
JFrame=新JFrame(“主”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(新的MyMainUI());
frame.pack();
frame.setLocationByPlatform(真);
frame.setVisible(true);
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
createAndShowGui();
}
});
}
}
@抑制警告(“串行”)
类MyMainUI扩展了JPanel{
公共静态最终字符串IMG\u URL\u PATH=”http://duke.kenai.com/Oracle/OracleStrat.png";
专用静态最终整型预调W=900;
专用静态最终int PREF_H=650;
私有JLabel thumblblbl=新JLabel();
私有JButton thumbBtn=新JButton(“获取图像”);
公共MyMainUI(){
thumbtn.addActionListener(新ActionListener()){
已执行的公共无效操作(操作事件arg0){
ThumbTn.setEnabled(错误);
最终ImageDownloader imgDownLoader=新ImageDownloader(IMG_URL_路径);
imgDownLoader.execute();
addPropertyChangeListener(新的ImgDownLoaderListener(imgDownLoader));
}
});
JPanel btnPanel=新的JPanel();
btnPanel.add(thumbtn);
setLayout(新的BorderLayout());
添加(新的JScrollPane(thumbLbl),BorderLayout.CENTER);
添加(btnPanel,BorderLayout.PAGE_END);
}
@凌驾
公共维度getPreferredSize(){
返回新维度(PREF_W,PREF_H);
}
私有类ImgDownLoaderListener实现PropertyChangeListener{
ImageDownloader-imgDownLoader;
公共imgDownLoader列表器(ImageDownloader imgDownLoader){
this.imgDownLoader=imgDownLoader;
}
@凌驾
公共作废属性更改(属性更改事件evt){
//秋千工人完成了
if(evt.getNewValue().equals(SwingWorker.StateValue.DONE)){
ThumbTn.setEnabled(真);
试一试{
ImageIcon icon=imgDownLoader.get();
如果(图标!=null){
thumbLbl.setIcon(图标);
}
}捕捉(中断异常e){
e、 printStackTrace();
}捕获(执行例外){
e、 printStackTrace();
}
}
}
}
}
类ImageDownloader扩展SwingWorker{
私有字符串imageUrlPath;
公共ImageDownloader(字符串imageUrlPath){
this.imageUrlPath=imageUrlPath;
}
@凌驾
受保护的ImageIcon doInBackground()引发异常{
试一试{
URL imgUrl=新URL(imageUrlPath);
BuffereImage img=ImageIO.read(imgUrl);
返回新的ImageIcon(img);//返回ImageIcon
}捕获(格式错误){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}
return null;//如果发生错误,则返回null
}
}

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

我自己,我通常用SwingWorker来处理类似的事情。除了在后台线程上做事情外,它还有许多其他优点,包括因为它是未来的,它可以返回值,并且它允许轻松使用PropertyChangeListeners。谢谢你的评论,我不知道SwingWorker,它似乎是一个很好的选择。我会试试的。另外:1)你的英语很好。2) 不要使用鼠标侦听器来响应JButton按钮,而是使用ActionListener——这就是它的用途。有微妙但重要的区别,一个重要的区别是,如果JButton被禁用,鼠标侦听器仍然会响应,而ActionListener(正确地)不会。1)感谢google traduction(这是一个笑话),2)我想知道为什么在某些情况下,当我的按钮被禁用时,侦听器会工作,我想我的代码中有很多类似的错误,这将是开源的,这就是我不想犯大错误的原因,我感谢你的评论,我希望当我发布我的应用程序时,像你这样的人对我说什么不对。我会尝试你说的一切,重新制作我的示例,并使此线程得到解决谢谢你的示例,即使我认为,我自己也能做到
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);
  }
}
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
   }

}