簡體   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();
        }
    }
    
}

嗨,大家好,

當我嘗試使用動作啟動(例如按鍵)for 循環更新 JLabel/JButton/JPanel 時,它會在 for 循環結束后首先更新框架,即使我在 for 循環中更新了框架使用 frame.repaint()...

我找不到任何關於這個問題的帖子......

我能做什么?

請幫助!

如評論中所述,您將需要一個Swing Timer來執行任務。 現在, move()方法中的for循環正在阻止 EDT,您將看不到面板移動。 只有在 EDT 可用並且可以更新 GUI 時,您才會看到最終的面板位置。

為了讓您的代碼正常工作,我建議如下:

擺脫move()方法及其for循環。 相反,使用 Swing Timer 的ActionPerformed事件中的計數器來執行類似的操作。 下面是您快速修改的代碼以使用 Swing 計時器。 閱讀代碼中的注釋:

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);
    }
}

這是您的代碼的另一個版本,它允許您在窗口內向不同方向移動面板。 除非您選擇暫停動畫的鍵盤數字鍵盤5按鈕或完全停止動畫的ESCAPE鍵,否則面板始終處於連續運動狀態。 空格鍵在動畫停止后重新啟動動畫。 其他數字鍵盤鍵和光標鍵可在特定方向移動面板。 如果你只是讓面板四處漂浮,當它碰到窗戶邊緣時,它會隨機改變到三個相反方向中的任何一個。 數字鍵盤+-鍵增加和減少面板的移動增量,鍵盤=-鍵將增加和減少 Swing Timer Delay Rate(本質上是動畫速度)。

這是示例代碼:

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