繁体   English   中英

仅在Java Swing中重绘后触发事件?

[英]Trigger event only after repaint in Java Swing?

我在java中制作一个简单的棋盘游戏,我想要制作一个骰子动画。 所以我用这样的骰子闪光照片:

public Timer roll_dice = new Timer(50, this);
...
public void actionPerformed(ActionEvent evt) {
        if(roll_dice.getDelay() > 500){
            roll_dice.setDelay(50);
            roll_dice.stop();
            movePiece();
        }else{
            roll_dice.setDelay(roll_dice.getDelay() + 50);
            dice_panel.repaint(0);
        }
    }
}

movePiece(){
    //do some more painting
}

因此,模具将如此显示随机数几次,然后慢慢地确定一个数字。 完成之后我想调用movePiece()方法。 然而,实际上,重新出现偶尔并将所有内容拧紧,以便在骰子卷实际完成动画之前调用movePiece()

有没有人有任何想法,我怎么能在最后的重绘发生后调用movePiece?

因此,模具将如此显示随机数几次,然后慢慢地确定一个数字。 完成之后我想调用movePiece()方法。 然而,实际上,重新出现偶尔并将所有内容拧紧,以便在骰子卷实际完成动画之前调用movePiece()。

这里让我担心的是你的绘画偶尔发生的原因 - 它根本不应该这样做,也许就是你需要解决的问题。 我想知道你每次进行绘图时是否正在读取文件中的图像,或者其他原因是为了减慢绘图速度。 如果您在此问题上需要更多帮助,那么您必须向我们提供有关您如何进行绘画的更多信息。 无论如何,你应该避免使程序逻辑依赖于绘画,因为你无法完全控制何时或甚至是否会发生绘画。

为什么不在程序启动时简单地将滚动骰子图像放入ImageIcons,然后在Swing Timer中,在JLabel中交换图标,而不是重绘图像并调用repaint()。 然后在延迟时间足够长的时候停止你的计时器,如果阻止,移动你的作品。

因此,假设您有几个骰子,每个骰子都可以由JLabel显示,该JLabel保存在名为diceLabels的JLabel数组中,ImageIcons可以保存在名为diceIcons的数组中。 然后你可以这样做:

  public void actionPerformed(ActionEvent e) {
     if (roll_dice.getDelay() > 500) {
        roll_dice.setDelay(50);
        roll_dice.stop();
        movePiece(); // I like this -- this shouldn't change
     } else {
        roll_dice.setDelay(roll_dice.getDelay() + 50);
        // dice_panel.repaint(0);
        for (JLabel dieLabel : diceLabels) {
           int randomIndex = random.nextInt(diceIcons.length);
           dieLabel.setIcon(diceIcons[randomIndex]);
        }
     }
  }

当你调用movePiece()时我喜欢你的逻辑,我认为这应该保持不变。

您可以在另一个线程中调用滚动并将当前线程连接()到滚动线程。 这样主代码将等待滚动螺纹死亡(完成滚动)。

public void actionPerformed(ActionEvent evt) {
    if(roll_dice.getDelay() > 500){
        Thread rollerThread = new RollerThread();
        rollerThread.start();
        rollerThread.join();
        movePiece();
    }
    else{
        roll_dice.setDelay(roll_dice.getDelay() + 50);
        dice_panel.repaint(0);
    }
}

private RollerThread extends Thread
{
    public void run(){
        roll_dice.setDelay(50);
        roll_dice.stop();
    }
}

但是,这可能不适用于EDT - 因为重绘应该安排到队列中。 也许你可以使用SwingUtilities.invokeAndWait()举办活动:

public void actionPerformed(ActionEvent evt) {
    Thread thread = new Thread(){
        public void run(){
            if(roll_dice.getDelay() > 500){
                SwingUtilities.invokeAndWait(new Runnable(){
                     public void run(){
                         roll_dice.setDelay(50);
                         roll_dice.stop();
                     }
                });
                movePiece();
            }
            else{
                 roll_dice.setDelay(roll_dice.getDelay() + 50);
                 dice_panel.repaint(0);
            }
        }
    };
    thread.start();
}

如果你把这个调用放到movePiece();什么变化吗movePiece(); SwingUtilities.invokeLater(Runnable);

if(roll_dice.getDelay() > 500){
    roll_dice.setDelay(50);
    roll_dice.stop();

    SwingUtilities.invokeLater(new Runnable() {
        public void run() { movePiece(); }
    });
}
...

暂无
暂无

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

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