repaint()Jpanel在Event之后不工作

时间:2015-04-04 04:53:58

标签: multithreading events jpanel javabeans repaint

我是新学习重绘g编程方法,我正在尝试用grahpics制作一个简单的Rock paper sccissors动画。我正在使用netbeans

上下文:2个java clases:PPT.java扩展jpanel和netbeans JFrame表单。 我将PPT作为一个bean添加到JFRame上,它渲染了很好的开始动画(向下滑动并调整了rockpaper图像的大小......) 在动画之后我尝试不同的事件,比如点击豆子并回想起PPT.motor方法,他是重新定位事物并调用重印和睡眠以制作动画的人。

单击并触发事件后,执行在调用方法电机(几乎最后一个通道)之前平稳运行。 但是当程序必须第二次进入电机时它会在那里停留一段时间而没有错误,不会在窗口中打印任何内容,如果你点击多次它会打印出小而巨大而没有动画的图像。

我几乎可以肯定我的问题来自于不处理好的线程,但谁知道。

这是PPT.java

package ppt;

import com.sun.org.apache.bcel.internal.classfile.Constant;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import static java.lang.Thread.sleep;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;


public class PPT extends JPanel{
//Variables de Imagen buffered para prevenir FLIKR
private BufferedImage piedra;
private BufferedImage tijera;
private BufferedImage papel;

//Game Variables
private int cpu;//CPU choice
private int j1;//J1 choice
private int totalCPU;//score
private int totalJ1;//score
private int ganaRonda;//0 ties, 1 j1 win -1 cpu win
//
private static GUI ventana;//Declaramos asi la variable ventana para poder acceder a sus Variables fuera del main.
//piedra= rock papel=paper XY=cordinate var TXTY= SizeVar
private int piedraX=240, piedraXCPU;//Cordenada X para renderizar la imagen
private int piedraY=280, piedraYCPU;//Coordenada Y para renderizar la imagen
private int piedraTX=242;//Tamaño de salida de la imagen en X 900
private int piedraTY=242;//Tanaño de salida de la imagen en Y  645
private int papelX=444, papelXCPU=-100;//Cordenada X para renderizar la imagen
private int papelY=248, papelYCPU=-100;//Coordenada Y para renderizar la imagen
private int papelTX=300;//Tamaño de salida de la imagen en X 600
private int papelTY=300;//Tanaño de salida de la imagen en Y  376
private int tijeraX=280, tijeraXCPU=-100;//Cordenada X para renderizar la imagen
private int tijeraY=240, tijeraYCPU=-100;//Coordenada Y para renderizar la imagen
private int tijeraTX=400;//Tamaño de salida de la imagen en X 210
private int tijeraTY=400;//Tanaño de salida de la imagen en Y  400
private Color color1=Color.RED;//Color de la caja izq 1
private Color color2=Color.BLUE;//Color de la caja izq 2

public static void main(String[] args) {
    // TODO code application logic here
//INSTANCE OF JFRAMEFORM
    ventana =new GUI("Piedra Papel Tijera");

    ventana.setLocationRelativeTo(null);//Centra la ventana en el media
    ventana.setVisible(true);//Hace visible la ventana
    ventana.pPT1.motor(4);//pPT1 IS THIS CLASS INSTANCED FROM JFRAME AS BEAN

}
public PPT (){
    //CONSTRUCTOR getting images
    try {
        this.piedra = ImageIO.read(getClass().getResource("piedra.png"));
        this.papel = ImageIO.read(getClass().getResource("papel.png"));
        this.tijera = ImageIO.read(getClass().getResource("tijeras.png"));
    } catch (IOException ex) {
        Logger.getLogger(PPT.class.getName()).log(Level.SEVERE, null, ex);
    }
    this.setSize(800, 700);//Establece el tamaño del jpanel a 800x700
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g); 
    //THIS draw the Scores at the left of the screen
    g.setFont(new Font("Arial",Font.BOLD,42));//establece la fuente
    g.setColor(color1);//ColorRojo
    g.fillRect(1, 350, 42, 84);//Dibuja el rectangulo Del Jugador
    g.setColor(color2);//ColorAzul
    g.fillRect(1, 264, 42, 84);//dibuja el rectangulo azul
    g.drawString(Integer.toString(totalJ1) , 4, 420);//dibuja la puntuacion del J1 en azul
    g.setColor(color1);//ColorRojo
    g.drawString(Integer.toString(totalCPU) , 4, 313);//dibuja la puntuacion de la CPU en rojo

    /THIS draw the images
    g.drawImage(piedra, piedraX, piedraY,piedraTX,piedraTY,null);//pintamos la Image de la variable en la Posicion XY y con el tamaño TX TY
    g.drawImage(papel, papelX, papelY,papelTX,papelTY,null);
    g.drawImage(tijera, tijeraX, tijeraY,tijeraTX,tijeraTY,null);

}

    public void cpuTira (){
//THIS generate RANDOM choose to cpu
    cpu=(int) (Math.random() * (4 - 1)) + 1;
}
 //This is the GameLoopHandler
public void motor (int num){

    if (num==4){
        //THIS RESET THE ORIGINAL VALUES OF vars FOR START AGAIN THE ANIMATION OF THE FIRST STAGE
piedraX=240;//Cordenada X para renderizar la imagen
piedraY=280;//Coordenada Y para renderizar la imagen
piedraTX=242;//Tamaño de salida de la imagen en X 900
piedraTY=242;//Tanaño de salida de la imagen en Y  645
papelX=444;//Cordenada X para renderizar la imagen
papelY=248;//Coordenada Y para renderizar la imagen
papelTX=300;//Tamaño de salida de la imagen en X 600
papelTY=300;//Tanaño de salida de la imagen en Y  376
tijeraX=280;//Cordenada X para renderizar la imagen
tijeraY=240;//Coordenada Y para renderizar la imagen
tijeraTX=400;//Tamaño de salida de la imagen en X 210
tijeraTY=400;//Tanaño de salida de la imagen en Y  400
//THIS MOVE THE IMAGES down until near the bottom and resize them 
        while (piedraY<500){
            if (piedraY>400){
                piedraTX--;
                piedraTY--;
                papelTX--;
                papelTY--;
                tijeraTX-=2;
                tijeraTY-=2;
            }
            if(tijeraY>359)
                tijeraX++;
            if(papelY>385)
                papelX++;
            piedraY++;
            tijeraY++;
            papelY++;


            repaint();
            try {//CUANTO MAS TIEMPO DE SLEEP MAS LENTA VA LA ANIMACION (FPS)
                Thread.sleep(18);
            } catch (InterruptedException ex) {
                Logger.getLogger(PPT.class.getName()).log(Level.SEVERE, null, ex);
            }
        }


    }

}
//THIS METHOD IS called by the event in JFRAME FORM
public void controlJuego(int jugador1){
    j1=jugador1;//set the choice of j1
    cpuTira();//set the choice of CPU


    //Calculate win 1 rock, 2paper,3 scissors
    switch(j1){
        case 1:
            if(cpu==1)
                ganaRonda=0;
            if(cpu==2)
                ganaRonda=-1;
            if(cpu==3)
                ganaRonda=1;
            break;
        case 2:
            if(cpu==1)
                ganaRonda=1;
            if(cpu==2)
                ganaRonda=0;
            if(cpu==3)
                ganaRonda=-1;
            break;
        case 3:
            if(cpu==1)
                ganaRonda=-1;
            if(cpu==2)
                ganaRonda=1;
            if(cpu==3)
                ganaRonda=0;
    }
    //Animation of "Fight" Currently i just want to repeat the start animation
    System.out.println("hellow");//it printed hellow quicly
    motor(4);//4 = intro animation
    System.out.println(Integer.toString(ganaRonda));//it printed the variable after half minut and dindt redender nothing.
}


}

JFrame表单具有默认的netbeans代码,并且已部署了bean。 因此,线程混乱可能会导致我在JFrame中调用eventClick然后爆炸。

感谢您的帮助,对墙信息感到抱歉,我只是想了解这件事。

1 个答案:

答案 0 :(得分:0)

解决方案: 我开始了一个新的NOT netbeans GUI基础项目,其中包含此代码https://www.youtube.com/watch?v=_ix-jCzG53A

并将Ant类修改为我自己的游戏类。

另外,为了让动画顺利运行更新,我必须创建一个新的线程代码,必须在EDT上运行,并且计时器每10ms重复一次或者你想要的延迟。

(像这样,但将setRepetas设置为true)10ms而不是300 定时器计时器=新计时器(10,新的ActionListener(){ https://stackoverflow.com/a/22968559/4748324

像这样的最终代码

int delay=10;

//Creamos un timer que se repetira para actualizar la posicion de los elementos adecuadamente en el EDT
 Timer piedraJtimer = new Timer(delay, new ActionListener(){
/*So the Timer object will create a new thread, delay for 300 milliseconds, and then call the 'actionPerformed' method.
This will happen on the Timer's thread. It's not recommended to change UI elements from any thread except for the EDT,
so we use the invokeLater method which causes swing to run the runnable on the EDT itself - so back on the original thread.*/
 @Override
 public void actionPerformed(ActionEvent e) {
     SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {

           // runs code on the EDT to edit UI elements (recommended way)
            if (piedraY!=280){//if StoneY is not in 280 make animation
                if (piedraY<444){
                    piedraX++;
                }
                piedraY--;
            }else//if Stone Y is in 280 y and the Cpu Stone or Cpu paper or Cpu sicssors are in place redy to roll out 
            if(piedraYCPU==404 || tijeraYCPU==400 || papelYCPU==400)
                piedraX-=4;//Roll out sliding to left
            if(piedraX<=0){//if Stone rolled out, set controls On and Stop the recursive timer
                puedeAccionar = true;
                piedraJtimer.stop();//Canceling the timer repeats.

            }
        }

     });  
 }
});

重绘();方法是在每个延迟毫秒的游戏循环中进行调用