由于延迟,Java Swing绘制错误图片
我是swing编程新手,在线程同步方面遇到了一些困难 我试图迭代一个数组,在每个索引处创建一个JPanel和一个JFrame,并希望在每个面板上绘制一幅图片。与数组中存储的值相关的图片。 但所有帧/面板仅保存最后一个数组条目的图片。我认为这是由于一个单独的摆动线程(?),但我不知道如何改变它。 你能帮我吗由于延迟,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
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点,我现在需要睡觉;)