简体   繁体   English

使用动作启动的 for 循环不工作(重新绘制)更新 JFrame 上的 JLabel

[英]Update JLabel on JFrame using action-started for-loop not working (repainting)

import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import javax.swing.*;

public class show{
    
    static JFrame frame = new JFrame();
    static JPanel panel = new JPanel();
    
    public static void main(String[] args) throws IOException, InterruptedException {
        
                //setup Frame
        frame.setVisible(true);
        frame.setSize(1500, 500);
        frame.setLayout(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.getContentPane().setBackground(new Color(0,120,240));
        frame.addKeyListener(new KeyListener() {

            @Override
            public void keyPressed(KeyEvent e) {
                
                if(e.getKeyCode() == KeyEvent.VK_SPACE) {
                    try {
                        move();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                }
                
            }

            @Override
            public void keyTyped(KeyEvent e) {
                // TODO Auto-generated method stub
                
            }

            @Override
            public void keyReleased(KeyEvent e) {
                // TODO Auto-generated method stub
                
            }
            
        });
        
        //setup Panel
        panel.setVisible(true);
        panel.setLocation(150,150);
        panel.setSize(150, 50);
        panel.setBackground(new Color(0,0,0));
        frame.add(panel);
        
        frame.repaint();
    }
    
    public static void move() throws InterruptedException {
        for(int i=0;i<20;i++) {
            panel.setLocation(panel.getLocation().x+20,panel.getLocation().y+20);
            Thread.sleep(100);
            frame.repaint();
        }
    }
    
}

Hi guys,嗨,大家好,

when I try to update a JLabel/JButton/JPanel using a action-started (ex. key-press) for-loop, it first updates the frame after the for loop is over, even though I update the frame in the for-loop with frame.repaint()...当我尝试使用动作启动(例如按键)for 循环更新 JLabel/JButton/JPanel 时,它会在 for 循环结束后首先更新框架,即使我在 for 循环中更新了框架使用 frame.repaint()...

I couldn't find any posts to this problem...我找不到任何关于这个问题的帖子......

What can I do?我能做什么?

pls help!请帮助!

As mentioned in comments, you will need aSwing Timer to carry out the task.如评论中所述,您将需要一个Swing Timer来执行任务。 Right now, the for loop within the move() method is holding up the EDT and you won't see the panel move.现在, move()方法中的for循环正在阻止 EDT,您将看不到面板移动。 You will only see the final panel position once the EDT is free and can update the GUI.只有在 EDT 可用并且可以更新 GUI 时,您才会看到最终的面板位置。

In order to get your code working I would suggest the following:为了让您的代码正常工作,我建议如下:

Get rid of the move() method and its for loop.摆脱move()方法及其for循环。 Instead, utilize a counter within a Swing Timer's ActionPerformed event to carry out the similar thing.相反,使用 Swing Timer 的ActionPerformed事件中的计数器来执行类似的操作。 Below is your code quickly modified to work with a Swing Timer.下面是您快速修改的代码以使用 Swing 计时器。 Read the comments in code:阅读代码中的注释:

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import javax.swing.*;

public class show{
    static JFrame frame = new JFrame();
    static JPanel panel = new JPanel();
    static Timer animationTimer;       // Swing Timer.
    static int animationSpeed = 100;
    static int counter; 
    
    
    public static void main(String[] args) throws IOException, InterruptedException {
        frame.setVisible(true);
        frame.setSize(1500, 500);
        frame.setLayout(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.getContentPane().setBackground(new Color(0, 120, 240));
        
        frame.addKeyListener(new KeyListener() {
            @Override
            public void keyPressed(KeyEvent evt) {
                if(evt.getKeyCode() == KeyEvent.VK_SPACE) {
                    /* Set the panel for location for another restart.
                       Every time the space-Bar is hit the Panel will
                       reset and move down again.                 */
                    panel.setLocation(150,150); 
                    
                    // Counter instead of `for` loop:
                    counter = 0;
                    
                    /* Start the Swing Timer. The real work is done within
                       the actionPerformed event of the timer
                    */
                    animationTimer.start();
                }
            }

            @Override
            public void keyTyped(KeyEvent e) {
                // TODO Auto-generated method stub
            }

            @Override
            public void keyReleased(KeyEvent e) {
                // TODO Auto-generated method stub
            }
            
        });
        
        //setup Panel
        panel.setVisible(true);
        panel.setLocation(150,150);
        panel.setSize(150, 50);
        panel.setBackground(new Color(0,0,0));
        frame.add(panel);
        
        
        // The ActionListern for the Swing Timer ... Used for Animation of Panel.
        ActionListener performTask = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                panel.setLocation(panel.getLocation().x + 20, panel.getLocation().y + 20);
                
                // If the counter reaches 20 then stop the Swing Timer.
                if (counter == 20) {
                    animationTimer.stop();
                }
                /* Incremant the counter by 1 upon each timer cycle. 
                   The Timer Delay is set with the animationSpeed 
                   member variable which is currently set to 100 
                   milliseconds. So, every100 milliseconds the 
                   counter is incremented and the panel is moved
                   upon the next cycle.                */
                counter++;
            }
        };
        
        /* The swing timer delay time (100 milliseconds) and the ActionListener
           (performTask) which contains the ActionPerformed event that will be 
           fired on each timer cycle. The Timer will continuously cycle every 
           100 milliseconds until told to Stop.        */
        animationTimer = new Timer(animationSpeed, performTask);
    }
}

Here is another version of your code which allows you to move the panel in different directions within the Window.这是您的代码的另一个版本,它允许您在窗口内向不同方向移动面板。 The panel is always in continuous motion unless you select the Keyboard Number Pad 5 button which pauses the animation or the ESCAPE key which stops the animation altogether.除非您选择暂停动画的键盘数字键盘5按钮或完全停止动画的ESCAPE键,否则面板始终处于连续运动状态。 The Space Bar restarts the animation after it has been stopped.空格键在动画停止后重新启动动画。 Other Number Pad keys and cursor keys move the panel in specific directions.其他数字键盘键和光标键可在特定方向移动面板。 If you just let the panel float around, when it hits a window edge, it will randomly change to any one of three opposing directions.如果你只是让面板四处漂浮,当它碰到窗户边缘时,它会随机改变到三个相反方向中的任何一个。 The Number Pad + and - keys increases and decreases the movement increments of the Panel and the Keyboard = and - keys will increase and decrease the Swing Timer Delay Rate (in essance, the Animation Speed).数字键盘+-键增加和减少面板的移动增量,键盘=-键将增加和减少 Swing Timer Delay Rate(本质上是动画速度)。

Here is the example code:这是示例代码:

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;


public class Show {

    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    JLabel animationSpeedLbl;
    JLabel label;
    Timer animationTimer;
    
    int animationSpeed = 5, increment = 1;
    int curX = 0, curY = 0, key = 0;
    java.util.List<Integer> allowablekeys = Arrays.asList(
            KeyEvent.VK_SPACE, KeyEvent.VK_ESCAPE, KeyEvent.VK_UP, KeyEvent.VK_DOWN,
            KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT, KeyEvent.VK_NUMPAD7, KeyEvent.VK_NUMPAD8,
            KeyEvent.VK_NUMPAD9, KeyEvent.VK_NUMPAD4, KeyEvent.VK_NUMPAD5, KeyEvent.VK_NUMPAD6,
            KeyEvent.VK_NUMPAD1, KeyEvent.VK_NUMPAD2, KeyEvent.VK_NUMPAD3, KeyEvent.VK_ADD,
            KeyEvent.VK_SUBTRACT, KeyEvent.VK_EQUALS, KeyEvent.VK_MINUS);

    public static void main(String[] args) {
        new Show().startApp(args);
    }

    private void startApp(String[] args) {
        //setup Frame
        frame.setLayout(new FlowLayout());
        frame.setPreferredSize(new java.awt.Dimension(800, 700));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.getContentPane().setBackground(new Color(0, 120, 240));
        frame.addKeyListener(new KeyListener() {
            @Override
            public void keyPressed(KeyEvent e) {
                int curKey = -1;
                if (animationTimer.isRunning()) {
                    curKey = key;
                }
                int keyNum = e.getKeyCode();

                if (!allowablekeys.contains(keyNum)) {
                    return;
                }
                key = keyNum;
                System.out.println(key);

                switch (key) {
                    case KeyEvent.VK_SPACE:
                        if (!animationTimer.isRunning()) {
                            key = KeyEvent.VK_DOWN;
                            label.setText("<html><center><font size='2' color=#DCDCDC>"
                                    + "Press Numpad Keys To<br>Change Direction</html>");
                            animationTimer.start();
                        } break;
                    case KeyEvent.VK_ESCAPE:
                        if (animationTimer.isRunning()) {
                            animationTimer.stop();
                        } break;
                        
                    case KeyEvent.VK_ADD:
                        if (animationTimer.isRunning()) {
                            increment++;
                            if (increment > 50) {
                                // Max allowable is an increment of 50. You can change this.
                                increment = 50;
                            }
                            key = curKey;
                        } break;
                        
                    case KeyEvent.VK_SUBTRACT:
                        if (animationTimer.isRunning()) {
                            increment--;
                            if (increment < 0) {
                                // Min allowable is an increment of 0. You can change this.
                                increment = 0;
                            }
                            key = curKey;
                            key = curKey;
                        } break;
                        
                    case KeyEvent.VK_EQUALS:
                        if (animationTimer.isRunning()) {
                            animationSpeed++;
                            animationTimer.setDelay(animationSpeed);
                            if (animationSpeed > 1000) {
                                // Max allowable is an increment of 50. You can change this.
                                animationSpeed = 1000;
                            }
                            key = curKey;
                        } break;
                    
                    case KeyEvent.VK_MINUS:
                        if (animationTimer.isRunning()) {
                            animationSpeed--;
                            if (animationSpeed < 0) {
                                /* Min allowable is an Animation Speed of 0. You can not 
                                   go less than 0. Since the value is a delay time ( in 
                                   milliseconds), the lower the number, the faster the
                                   animation.                               */
                                animationSpeed = 0;
                            }
                            animationTimer.setDelay(animationSpeed);
                            key = curKey;
                        } break;
                    default:
                        break;
                }
                frame.setTitle("Animation Speed: " + animationSpeed  + "  (Keyboard =/- to change)"
                             + "  |  Increment Level: " + increment + "  (Number Pad +/- to change)");
            }

            @Override
            public void keyTyped(KeyEvent e) {
                // Do nothing

            }

            @Override
            public void keyReleased(KeyEvent e) {
                // Do Nothing
            }
        });
        
        //setup Panel
        panel.setPreferredSize(new java.awt.Dimension(150, 50));
        panel.setBackground(new Color(0, 0, 0));
        
        label = new JLabel("<html><center><font size='2' color=#DCDCDC>"
                         + "Press Space-Bar To<br>Start Animation</html>");
        label.setForeground(Color.white);
        panel.add(label);
        frame.add(panel);
        frame.pack();

        // Using a Swing Timer...for animation
        ActionListener performTask = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
                // Random directional Options:
                int[] upOptions = {KeyEvent.VK_NUMPAD7, KeyEvent.VK_NUMPAD8, KeyEvent.VK_NUMPAD9};
                int[] downOptions = {KeyEvent.VK_NUMPAD1, KeyEvent.VK_NUMPAD2, KeyEvent.VK_NUMPAD3};
                int[] leftOptions = {KeyEvent.VK_NUMPAD7, KeyEvent.VK_NUMPAD4, KeyEvent.VK_NUMPAD1};
                int[] rightOptions = {KeyEvent.VK_NUMPAD9, KeyEvent.VK_NUMPAD6, KeyEvent.VK_NUMPAD3};
                switch (key) {
                    case KeyEvent.VK_NUMPAD7:
                        curX = panel.getLocation().x - increment;
                        curY = panel.getLocation().y - increment;
                        break;
                    case KeyEvent.VK_NUMPAD8:
                    case KeyEvent.VK_UP:
                        curX = panel.getLocation().x;
                        curY = panel.getLocation().y - increment;
                        break;
                    case KeyEvent.VK_NUMPAD9:
                        curX = panel.getLocation().x + increment;
                        curY = panel.getLocation().y - increment;
                        break;
                    case KeyEvent.VK_NUMPAD2:
                    case KeyEvent.VK_DOWN:
                        curX = panel.getLocation().x;
                        curY = panel.getLocation().y + increment;
                        break;
                    case KeyEvent.VK_NUMPAD1:
                        curX = panel.getLocation().x - increment;
                        curY = panel.getLocation().y + increment;
                        break;
                    case KeyEvent.VK_NUMPAD4:
                    case KeyEvent.VK_LEFT:
                        curX = panel.getLocation().x - increment;
                        curY = panel.getLocation().y;
                        break;
                    case KeyEvent.VK_NUMPAD6:
                    case KeyEvent.VK_RIGHT:
                        curX = panel.getLocation().x + increment;
                        curY = panel.getLocation().y;
                        break;
                    case KeyEvent.VK_NUMPAD3:
                        curX = panel.getLocation().x + increment;
                        curY = panel.getLocation().y + increment;
                        break;
                    default:
                        return;
                }

                if (panel.getLocation().x <= 0 + increment) {
                    key = rightOptions[ThreadLocalRandom.current().nextInt(0, rightOptions.length)];
                    switch (key) {
                        case KeyEvent.VK_NUMPAD6:
                            curX = panel.getLocation().x + increment;
                            curY = panel.getLocation().y;
                            break;
                        case KeyEvent.VK_NUMPAD9:
                            curX = panel.getLocation().x + increment;
                            curY = panel.getLocation().y + increment;
                            break;
                        case KeyEvent.VK_NUMPAD3:
                            curX = panel.getLocation().x + increment;
                            curY = panel.getLocation().y - increment;
                            break;
                        default:
                            key = KeyEvent.VK_NUMPAD6;
                            curX = panel.getLocation().x + increment;
                            curY = panel.getLocation().y;
                            break;
                    }
                }

                else if (panel.getLocation().x >= (frame.getContentPane().getWidth() - panel.getWidth() - increment)) {
                    key = leftOptions[ThreadLocalRandom.current().nextInt(0, leftOptions.length)];
                    switch (key) {
                        case KeyEvent.VK_NUMPAD4:
                            curX = panel.getLocation().x - increment;
                            curY = panel.getLocation().y;
                            break;
                        case KeyEvent.VK_NUMPAD7:
                            curX = panel.getLocation().x - increment;
                            curY = panel.getLocation().y - increment;
                            break;
                        case KeyEvent.VK_NUMPAD1:
                            curX = panel.getLocation().x - increment;
                            curY = panel.getLocation().y + increment;
                            break;
                        default:
                            key = KeyEvent.VK_NUMPAD4;
                            curX = panel.getLocation().x - increment;
                            curY = panel.getLocation().y;
                            break;
                    }
                }
                else if (panel.getLocation().y <= 0) {
                    key = downOptions[ThreadLocalRandom.current().nextInt(0, downOptions.length)];
                    switch (key) {
                        case KeyEvent.VK_NUMPAD2:
                            curX = panel.getLocation().x;
                            curY = panel.getLocation().y + increment;
                            break;
                        case KeyEvent.VK_NUMPAD1:
                            curX = panel.getLocation().x - increment;
                            curY = panel.getLocation().y + increment;
                            break;
                        case KeyEvent.VK_NUMPAD3:
                            curX = panel.getLocation().x + increment;
                            curY = panel.getLocation().y + increment;
                            break;
                        default:
                            key = KeyEvent.VK_NUMPAD2;
                            curX = panel.getLocation().x;
                            curY = panel.getLocation().y + increment;
                            break;
                    }
                }
                else if (panel.getLocation().y >= (frame.getContentPane().getHeight() - panel.getHeight() - increment)) {
                    key = upOptions[ThreadLocalRandom.current().nextInt(0, upOptions.length)];
                    switch (key) {
                        case KeyEvent.VK_NUMPAD8:
                            curX = panel.getLocation().x;
                            curY = panel.getLocation().y - increment;
                            break;
                        case KeyEvent.VK_NUMPAD7:
                            curX = panel.getLocation().x - increment;
                            curY = panel.getLocation().y - increment;
                            break;
                        case KeyEvent.VK_NUMPAD9:
                            curX = panel.getLocation().x + increment;
                            curY = panel.getLocation().y - increment;
                            break;
                        default:
                            key = KeyEvent.VK_NUMPAD8;
                            curX = panel.getLocation().x;
                            curY = panel.getLocation().y - increment;
                            break;
                    }
                }
                panel.setLocation(curX, curY);
            }
        };
        animationTimer = new Timer(animationSpeed, performTask);
        
        java.awt.EventQueue.invokeLater(() -> {
            frame.setVisible(true);
            frame.setLocationRelativeTo(null);
        });
    }
}

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

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