简体   繁体   English

JLabel图形在错误的时间更改

[英]JLabel graphic changes at wrong time

I have a slot machine program with some graphics, and the graphic is supposed to change when you pull the lever and for some reason it changes the graphic after it goes through all of the other code first. 我有一个带有某些图形的老虎机程序,当您拉动操纵杆时该图形应该会更改,并且由于某种原因,它会先经过所有其他代码后更改该图形。 Have a look: 看一看:

Declare images: 声明图片:

static ImageIcon jImage = new ImageIcon("C:\\Users\\Harry\\Desktop\\jackpotLeverNotPulled.png");
static ImageIcon jackpot1 = new ImageIcon("C:\\Users\\Harry\\Desktop\\jackpotimage1.png");
static ImageIcon jackpotPulled = new ImageIcon("C:\\Users\\Harry\\Desktop\\jackpotLeverPulled.png");

Now I add to panel: 现在,我添加到面板中:

static JLabel jlb = new JLabel(jImage);

Now I want the image to change when a certain area is clicked on my panel but the main jackpot code runs first and then the image changes: 现在,我想在面板上单击某个区域时更改图像,但是首​​先运行主要累积奖金代码,然后更改图像:

public void mousePressed(MouseEvent e) {

        // Returns the X coordinate of where the mouse was click on the panel
        System.out.println("X Coordinate: " + e.getX() );


        //  Returns the Y coordinate of where the mouse was click on the panel
        System.out.println("Y Coordinate: " + e.getY() );    
        System.out.println();

        Scanner ansr = new Scanner(System.in);
        String yesno;

        int random =  (int)(Math.random() * 21 );
        int percentCheck =  (int)(Math.random() * 10 );

        if (e.getX ()>975 && e.getX ()<1159 && e.getY ()>82 && e.getY ()<218){
            jlb.setIcon(jackpotPulled);
            if (cashMoneyz<1) {

                System.out.println("Insufficient funds");
                image1.setIcon(jackpot1);
            } else {

                System.out.println("One dollar has been removed from you slot machine balance");
                cashMoneyz--;
                try {
                    System.out.println("Spinning...");
                    Thread.sleep(1000);
                    System.out.println("Spinning...");
                    Thread.sleep(1000);
                    System.out.println("SPINNINGGGGG...OMG SOOO INTENSE");
                    Thread.sleep(1000);
                } catch (InterruptedException ie)
                {
                }

            }   
            System.out.println("You have this much money (in dollars) left in your slot machine balance: " + cashMoneyz);
            System.out.println("");
            System.out.println("----------------------------------------------------------------------------------");
        }

It does the if statements and try catches and only changes the graphic to jackpotPulled at the end of everything. 它执行if语句并尝试捕获,并且仅在一切结束时将图形更改为jackpotPulled。 Thanks in advance :) 提前致谢 :)

There are basically 2 problems in your code: 您的代码中基本上有2个问题:

1) A call to label.setImage() won't update immediately, as this is true for everything in AWT and Swing. 1)label.setImage() 的调用不会立即更新,因为对于AWT和Swing中的所有情况都是如此。 Any time a repaint request is fired, it is simply added to a repaint queue, that will wait patiently for all other tasks done in the EDT (Event Dispatching Thread) to finish. 每当重新绘制请求被触发时,它就会被简单地添加到重新绘制队列中,该队列将耐心等待在EDT(事件调度线程)中完成的所有其他任务。 But since you do other things in the mousePressed() , they will run first. 但是由于您在mousePressed()做了其他事情,它们将首先运行。 A simple solution for this would be to do the computing in mouseReleased() . 一个简单的解决方案是在mouseReleased()进行计算。 But a bigger problem exists. 但是存在更大的问题。

2) What you are currently doing is "starving" the EDT - a bad programming practice - as all screen related invocations must be executed immediately. 2)您当前正在做的是使EDT处于“饥饿状态”,这是一种不良的编程习惯,因为所有与屏幕相关的调用都必须立即执行。 Sleeping the EDT won't allow any repaints to take place while running. 休眠EDT不允许在运行时进行任何重新绘制。 This is true for any long running tasks as well. 对于任何长时间运行的任务也是如此。 Its solution is to run the non-painting calls in a different thread: 它的解决方案是在另一个线程中运行非绘画调用:

private volatile boolean isComputing = false;

public void mousePressed(MouseEvent evt) {
    if(isComputing)
        return;
    isComputing = true;

    // .
    // .
    // .
    // change icon here, or any
    // other swing related change.
    // .
    // .

    // run game
    new Thread(){
        public void run(){
           // all non-swing computations

           SwingUtilities.invokeLater(new Runnable() {
               public void run() {
                   // change back icons,
                   // and some other swing updates
               }
           }
           isComputing = false;
        }
    }.start();
}

An event handler ( mousePressed ) souldn't take a long time to complete, there should be no sleep s in it. 事件处理程序( mousePressed )不需要花费很长时间来完成,因此应该没有任何sleep As long as it runs (or sleeps), nothing else can happen. 只要它运行(或休眠),就什么也不会发生。 The runtime is waiting for the handler to return and displays the image after that. 运行时正在等待处理程序返回并在此之后显示图像。 I would move most of the code to a function called by a timer, and use a state variable to keep track of how intensely the wheels are spinning. 我会将大部分代码移至计时器调用的函数,并使用状态变量来跟踪车轮旋转的强度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM