我可以在计时器中使用线程吗?

时间:2019-05-27 18:00:49

标签: java swing actionlistener

此代码从开始按钮开始,但是如果选择了单选按钮倒数,则使用此代码,当倒数为0时,第二个帧出现,并应以用户输入的速度更改颜色,称为“ brzinaTreperenja2”(即转换为int,然后乘以1000(我的颜色是红色)。当我没有第二个actionListener时,会发生闪烁,并且闪烁的速度为1秒,但是当我这样做时,程序将冻结。你能帮我吗?

start.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        if(countdown.isSelected()){

        final Timer p = new Timer();
        display.setFont(new Font("Ariel", Font.BOLD,25));
        display.setBounds(150,75,120,20);
        p.scheduleAtFixedRate(new TimerTask(){
        int i = Integer.parseInt(odbrojavanje.getText());
        @Override
        public void run(){
        display.setText(""+(i--));
        if(i<0){
            p.cancel();
            drugi.setVisible(true);
            Thread t = new Thread();
            while(true){
                ActionListener al3 = new ActionListener(){
                public void actionPerformed(ActionEvent h){
            drugi.getContentPane().setBackground(boja.getBackground());
                try {
                    t.sleep(brzinaTreperenja2);
                } catch (InterruptedException ex) {
                    Logger.getLogger(PrviProzor.class.getName()).log(Level.SEVERE, null, ex);
                }
            drugi.getContentPane().setBackground(Color.red);
                try {
                    t.sleep(brzinaTreperenja2);
                } catch (InterruptedException ex) {
                    Logger.getLogger(PrviProzor.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            };
                javax.swing.Timer p = new javax.swing.Timer(1000, al3);
                p.start();
            }
        }
        }
        },0,1000);
    }
    }
});`

1 个答案:

答案 0 :(得分:0)

您的代码无视Swing线程规则:

  • 您正在从后台线程进行Swing调用,这样做很危险,并且可能导致意外地引发异常。
  • 您正在使用java.uti.Timer,并且应该使用javax.swing.Timer,因为后者的重复代码在Swing事件线程上运行。
  • 您有while (true)个不属于您的循环。计时器负责循环功能。
  • 您正在从while循环中反复创建和启动Swing计时器-为什么?

例如,以下代码使用JSlider设置闪烁频率,并使用一个复选框启动/停止Swing计时器,该计时器使主JPanel的背景颜色闪烁:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class BlinkEg extends JPanel {
    public static final Color COLOR = Color.RED;
    private JSlider slider = new JSlider(100, 1000, 500);
    private JCheckBox blinkBox = new JCheckBox("Blink");
    private Timer timer = new Timer(slider.getValue(), new TimerListener());

    public BlinkEg() {
        slider.setOpaque(false);
        slider.setMajorTickSpacing(200);
        slider.setMinorTickSpacing(10);
        slider.setPaintTicks(true);
        slider.setPaintLabels(true);
        setPreferredSize(new Dimension(400, 200));
        JPanel bottomPanel = new JPanel();
        bottomPanel.add(blinkBox);
        bottomPanel.setOpaque(false);

        blinkBox.setOpaque(false);
        blinkBox.addItemListener(evt -> {
            if (evt.getStateChange() == ItemEvent.SELECTED) {
                timer.start();
            } else {
                timer.stop();
                setBackground(null);
            }
        });

        slider.addChangeListener(evt -> {
            int value = slider.getValue();
            timer.setDelay(value);
        });

        setLayout(new BorderLayout());
        add(slider);
        add(bottomPanel, BorderLayout.PAGE_END);
    }

    private class TimerListener implements ActionListener {
        private boolean drawColor = false;

        @Override
        public void actionPerformed(ActionEvent e) {
            Color color = drawColor ? null : COLOR;
            BlinkEg.this.setBackground(color);
            drawColor = !drawColor;
        }
    }

    private static void createAndShowGui() {
        BlinkEg mainPanel = new BlinkEg();

        JFrame frame = new JFrame("BlinkEg");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

请注意,要更改Swing计时器的计时,只需调用其setDelay(...)方法:

// timer changed to rate set by JSlider:
slider.addChangeListener(evt -> {
    int value = slider.getValue();
    timer.setDelay(value);
});

要启动和停止闪烁,只需启动和停止计时器:

// timer start and stopped based on JCheckBox state
blinkBox.addItemListener(evt -> {
    if (evt.getStateChange() == ItemEvent.SELECTED) {
        timer.start();
    } else {
        timer.stop();
        setBackground(null);  // so always stops with baseline color
    }
});

Swing Timer使用一个ActionListener,它使用一个布尔值来决定将背景设置为哪种颜色,然后交换布尔值

private class TimerListener implements ActionListener {
    private boolean drawColor = false;

    @Override
    public void actionPerformed(ActionEvent e) {
        // choose color based on the state of drawColor
        Color color = drawColor ? null : COLOR;
        BlinkEg.this.setBackground(color);

        drawColor = !drawColor; // now toggle drawColor's boolean value
    }
}