多次更改JPanel的背景色

时间:2019-11-02 10:04:13

标签: java swing jpanel

我正在尝试编写一个小程序,其中包括更改基于时间的Panel的颜色。 现在,我只是在尝试其余部分。因此,我只用一个面板编写了一个小的Interface,我想在一个循环内多次更改颜色。 问题是,即使线程暂停了正确的时间,面板的颜色也无法正确更改。它有时只是在循环中而不是每次都改变。

我的界面类别:

import javax.swing.*;
import java.awt.*;

//creates the Interface
public class Interface extends JFrame {
    private JPanel frame1;

    public Interface (String titel) {
        super(titel);
        setSize(600, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.frame1 = new JPanel();
        this.frame1.setPreferredSize(new Dimension (200, 200));
        setLayout(new FlowLayout());
        add(frame1);
        this.setVisible(true);
    }

    public JPanel getFrame1() {
        return frame1;
    }

}

我的暂停类别:

import java.util.TimerTask;


//supposed to pause the thread by @pause amount of milliseconds
public class Pause extends TimerTask {
    private int pause;

    public Pause(int pause){
        this.pause = pause;
    }

    @Override
    public void run() {
        System.out.println("Timer"+ pause+" task started at:"+System.currentTimeMillis());
        pause();
        System.out.println("Timer task"+ pause+" ended at:"+System.currentTimeMillis());
    }

    public void pause() {
        try {
            Thread.sleep(this.pause);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

我的眨眼课

import javax.swing.*;
import java.awt.*;
public class Blink {
    private JPanel frame1;
    public Blink(Interface anInterface){
        this.frame1 = anInterface.getFrame1();
    }

    // blink should change the color of the JPanel inside my Frame. 
    // Its supposed to change to red for 200 ms
    // and then to white again for 1000 ms.
    // this should be repeated 10 times.
    public void blink() {
        Pause pause1 = new Pause(200);
        Pause pause2 = new Pause(1000);
        pause2.run();
        int i = 1;
        while(i <= 10){
            i++;
            frame1.setBackground(Color.red);
            frame1.repaint();
            pause1.run();
            frame1.setBackground(Color.white);
            frame1.repaint();
            pause2.run();
        }
    }

    public static void main ( String[] args ) {
        Interface anInterface = new Interface("Title");
        anInterface.setVisible(true);
        Blink blink = new Blink(anInterface);
        blink.blink();
    }
}

1 个答案:

答案 0 :(得分:1)

根据Concurrency to Swing,您不能简单地Thread.sleep Thread运行GUI的地方,因为它将冻结它,因此不会发生事件。相反,对于任何形式的动画或繁重的任务(将Thread.sleep视为一体),应使用Swing TimersSwing Workers。对于您来说,javax.swing.Timer更合适。

其用法示例:

public class Blink {
    private JPanel frame1;
    private int pause1TimesRan;
    private int pause2TimesRan;

    private Timer pauser1, pauser2;

    public Blink(Interface anInterface) {
        this.frame1 = anInterface.getFrame1();
        //Create pauser 1 with delay 200ms
        pauser1 = new Timer(200, e -> {
            if (pause1TimesRan == 10) {
                pauser1.stop();
                return;
            }
            Color color = randomColor();
            frame1.setBackground(color);
            System.out.println("Pauser #1 changed background to: " + color);
            pause1TimesRan++;
        });
        //Create pauser 2 with delay 1000ms
        pauser2 = new Timer(1000, e -> {
            if (pause2TimesRan == 10) {
                pauser2.stop();
                return;
            }
            Color color = randomColor();
            frame1.setBackground(color);
            System.out.println("Pauser #2 changed background to: " + color);
            pause2TimesRan++;
        });
    }

    private static Color randomColor() {
        return new Color((int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255));
    }

    public void blink() {
        pauser1.start();
        pauser2.start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Interface anInterface = new Interface("Title");
            anInterface.setVisible(true);
            Blink blink = new Blink(anInterface);
            blink.blink();
        });
    }

    static class Interface extends JFrame {
        private JPanel frame1;

        public Interface(String titel) {
            super(titel);
            setSize(600, 400);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.frame1 = new JPanel();
            this.frame1.setPreferredSize(new Dimension(200, 200));
            setLayout(new FlowLayout());
            add(frame1);
            this.setVisible(true);
        }

        public JPanel getFrame1() {
            return frame1;
        }

    }
}

一个不合时宜的建议是正确命名您的方法(和变量)。您调用了方法getFrame1(),但实际上它是JPanel而不是JFrame。因此,更好的名称可以是getPanel()。另外,关于SwingUtilities.invokeLater部分,请阅读What does SwingUtilities.invokeLater does