由于延迟,Java Swing绘制错误图片

由于延迟,Java Swing绘制错误图片,java,swing,synchronization,Java,Swing,Synchronization,我是swing编程新手,在线程同步方面遇到了一些困难 我试图迭代一个数组,在每个索引处创建一个JPanel和一个JFrame,并希望在每个面板上绘制一幅图片。与数组中存储的值相关的图片。 但所有帧/面板仅保存最后一个数组条目的图片。我认为这是由于一个单独的摆动线程(?),但我不知道如何改变它。 你能帮我吗 package help; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.Fi

我是swing编程新手,在线程同步方面遇到了一些困难

我试图迭代一个数组,在每个索引处创建一个JPanel和一个JFrame,并希望在每个面板上绘制一幅图片。与数组中存储的值相关的图片。 但所有帧/面板仅保存最后一个数组条目的图片。我认为这是由于一个单独的摆动线程(?),但我不知道如何改变它。 你能帮我吗

package help;

import java.awt.Graphics;
import java.awt.image.BufferedImage; 
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class SwingSynchro{

private JPanel jPanel;
private JFrame jFrame;
int array[] = {1,2,3,4};
int current;
private BufferedImage image1;
private BufferedImage image2;
private BufferedImage image3;
private BufferedImage image4;

public SwingSynchro(){

    //try{
    //    image1 = ImageIO.read(new File("someFilePath1.png"));
    //    image2 = ImageIO.read(new File("someFilePath2.png"));
    //    image3 = ImageIO.read(new File("someFilePath3.png"));
    //    image4 = ImageIO.read(new File("someFilePath4.png"));
    //} catch(IOException e){
    //    e.printStackTrace();
    //    System.out.println("wrong file path");
    //}// try catch

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

        current = array[i];
            System.out.println("current Number: "+ current + " at array index:" +i);

            jPanel = new JPanel(){
                private static final long serialVersionUID = 6859593162185621113L;

                @Override
                protected void paintComponent(Graphics g){
                    super.paintComponent(g);

                    switch(current){
                        case 1:
                            System.out.println("case 1");
                            //g.drawImage(image1, 10, 10, getWidth() - 20, getHeight() - 20, this);
                            break;
                        case 2:
                            System.out.println("case 2");
                           // g.drawImage(image2, 20, 20, getWidth() - 40, getHeight() - 40, this);
                            break;
                        case 3:
                            System.out.println("case 3");
                            //g.drawImage(image3, 10, 10, getWidth() - 20, getHeight() - 20, this);
                            break;
                        case 4:
                            System.out.println("case 4");
                            //g.drawImage(image4, 10, 10, getWidth() - 20, getHeight() - 20, this);
                            break;
                        default:
                            System.out.println("RELEASE THE KRAKEN!");
                            break;
                    }// switch
                }// paintComponent()
            };// anonymous class(extends JPanel)


        jFrame = new JFrame(String.valueOf(current));
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setResizable(false);
        jFrame.getContentPane().add(jPanel);
        jFrame.setSize(200, 250);
        jFrame.setLocation(i * 203, 0);
        jFrame.setVisible(true);
    }
}
}

Swing是单线程的。如果您想实时查看GUI的更新,请使用。Swing是单线程的。如果希望实时查看GUI的更新,请使用。

可以将JPanel实例化为一个匿名类,而不是将其作为一个内部类,并使用字段保存当前变量的值

private static class CustomJPanel extends JPanel {
    private static final long serialVersionUID = 6859593162185621113L;
    private final int current;

    private CustomJPanel(int current) {
        this.current = current;
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);

        switch(current){
            case 1:
                System.out.println("case 1");
                //g.drawImage(image1, 10, 10, getWidth() - 20, getHeight() - 20, this);
                break;
            case 2:
                System.out.println("case 2");
                // g.drawImage(image2, 20, 20, getWidth() - 40, getHeight() - 40, this);
                break;
            case 3:
                System.out.println("case 3");
                //g.drawImage(image3, 10, 10, getWidth() - 20, getHeight() - 20, this);
                break;
            case 4:
                System.out.println("case 4");
                //g.drawImage(image4, 10, 10, getWidth() - 20, getHeight() - 20, this);
                break;
            default:
                System.out.println("RELEASE THE KRAKEN!");
                break;
        }// switch
    }// paintComponent()
}
然后将其实例化为

jPanel = new CustomJPanel(current);

这样,您就可以确保在实例化JPanel时,
current
变量的值已经传递给它。

您可以将JPanel实例化为一个匿名类,而不是将其作为一个内部类,并使用字段来保存
current
变量的值

private static class CustomJPanel extends JPanel {
    private static final long serialVersionUID = 6859593162185621113L;
    private final int current;

    private CustomJPanel(int current) {
        this.current = current;
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);

        switch(current){
            case 1:
                System.out.println("case 1");
                //g.drawImage(image1, 10, 10, getWidth() - 20, getHeight() - 20, this);
                break;
            case 2:
                System.out.println("case 2");
                // g.drawImage(image2, 20, 20, getWidth() - 40, getHeight() - 40, this);
                break;
            case 3:
                System.out.println("case 3");
                //g.drawImage(image3, 10, 10, getWidth() - 20, getHeight() - 20, this);
                break;
            case 4:
                System.out.println("case 4");
                //g.drawImage(image4, 10, 10, getWidth() - 20, getHeight() - 20, this);
                break;
            default:
                System.out.println("RELEASE THE KRAKEN!");
                break;
        }// switch
    }// paintComponent()
}
然后将其实例化为

jPanel = new CustomJPanel(current);

这样,您就可以确保它已经被传递了当JPanel被实例化时,
current
变量所具有的值。

您谈到了多线程,但我认为您的代码中完全没有多线程。我错过了什么明显的东西吗?如果是的话,请给我看看。您的
可运行的
在哪里?你在哪里创建这个所谓的后台线程,你称之为
start()
?我只是假设存在异步线程,因为这是我对该行为的唯一解释。你的假设是不正确的。当您直接或间接地创建一个线程时,您将有后台线程,正如我前面提到的,我看不到您在哪里可以这样做。您谈到多线程,但我在代码中完全看不到多线程。我错过了什么明显的东西吗?如果是的话,请给我看看。您的
可运行的
在哪里?你在哪里创建这个所谓的后台线程,你称之为
start()
?我只是假设存在异步线程,因为这是我对该行为的唯一解释。你的假设是不正确的。当你直接或间接地创建一个后台线程时,你会有后台线程,正如我前面提到的,我看不到你在哪里可以这样做。我更喜欢写内部类而不是匿名类,只要它们超过5行。至于构造函数参数,我认为这是正确的(线程安全的)方法,因为在实例化JPanel时确实需要
current
变量的值。请考虑接受答案。@ EnUM:佐尔坦的编码没有错,事实上,这通常是常用的和有效的(如他所示)。1+。谢谢大家,我在使用真正的代码时仍然遇到一些问题(不过这个示例的解决方案非常好!)但现在是凌晨4点,我现在需要睡觉;)我更喜欢编写内部类而不是匿名类,只要它们超过5行。至于构造函数参数,我认为这是正确的(线程安全的)方法,因为在实例化JPanel时确实需要
current
变量的值。请考虑接受答案。@ EnUM:佐尔坦的编码没有错,事实上,这通常是常用的和有效的(如他所示)。1+。谢谢大家,我在使用真正的代码时仍然遇到一些问题(不过这个示例的解决方案非常好!)但现在是凌晨4点,我现在需要睡觉;)