Java按钮暂停图形更新

时间:2015-11-16 02:55:00

标签: java swing thread-sleep

所以我有一个班级,我必须制作一个程序来制作西蒙。 我知道我这样做的方式不一定是最好的方式,但是,他有一些模糊的要求,所以这就是我这样做的原因。

我的程序即将完成,但我有一个主要问题。 当我按下重置按钮时,我调用了一个名为reset的方法,该方法又将计算机设置为进行第一步。

在此期间,有图形更新。

当我单独调用reset方法时,它按预期工作当我按下重置按钮时,它会完成所有图形更新,直到它完成。 有没有办法在按下按钮后运行方法?

我的主要课程

package game;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import components.*;


@SuppressWarnings("serial")
public class Simonish extends JFrame implements ActionListener, MouseListener {


    private Color[][] ColorSwatch = {{Color.RED,Color.PINK},{Color.GREEN,Color.YELLOW}};
    private int width = 2;
    private int height = 2;
    private int panSize = 200;
    private SPane[][] panBoard;
    private int[] Sequence;
    private int CurrentSequenceLeingth = 0;
    private int SequenceLeingth = 10000;
    private Random r = new Random();
    boolean LastButtonClicked = false;
    private int LastButtonPressed = 0;
    private int sequencePart = 0;
    private boolean turn = false; //f=computer t=player
    Container pane;
    JPanel boardPanel;
    ScoreBoard scorePanel;
    private Simonish(){

        scorePanel = new ScoreBoard(0,width,panSize);
        scorePanel.getResetBtn().addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                    resetGame();
            }
        });
        this.setTitle("Simonish");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);
        pane = this.getContentPane();
        pane.setLayout(null);
        resetGame();
    }

    private void play(){
        if(!turn)
            ComputerTurn();
        else
            PlayerTurn();
    }

    private void ComputerTurn(){
        CurrentSequenceLeingth++;
        scorePanel.AddScore(1);
        PlaySequenc();
        turn = true;
    }

    private void PlayerTurn(){
            if((LastButtonPressed == Sequence[sequencePart]))
            {
                sequencePart++;
                LastButtonClicked = false;
            }else
            {
                loose();
                return;
            }
            if(sequencePart >= CurrentSequenceLeingth)
            {
                sequencePart = 0;
                turn = false;
                play();
            }
    }

    private void loose(){
        System.out.println("you loose");
        resetGame();
    }

    private void PlaySequenc(){
        for(int i = 0 ; i < CurrentSequenceLeingth ; i++)
        {
            panBoard[Sequence[i]/2][Sequence[i]%2].pressPane();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {}
        }
    }

    private void resetGame() {
        pane.removeAll();
        pane.setPreferredSize(new Dimension(width*panSize, (height) * panSize + 75));
        pane.add(scorePanel);
        initPanes();
        LastButtonClicked = false;
        LastButtonPressed = 0;
        initBtns();
        turn = false;
        CurrentSequenceLeingth = 3;
        Sequence = new int[SequenceLeingth];
        initSeq();
        pane.update(pane.getGraphics());        
        this.pack();
        this.setLocationRelativeTo(null);   
        this.setVisible(true);

        play();

    }
    private void initSeq() {

        for(int i = 0 ; i < SequenceLeingth ; i++)
        {
            Sequence[i] = r.nextInt(4);

        }

    }

    private void initBtns() {
        this.panBoard = new SPane[width][height];

        for(int w = 0; w < width; w++) {
            for(int h = 0; h < height; h++) {
                panBoard[w][h] = new SPane(w, h, panSize,ColorSwatch[w][h]);
                panBoard[w][h].addMouseListener(this);
                pane.add(panBoard[w][h]);
                pane.addMouseListener(this);
            }
        }
    }
    public static void main(String[] args){
        new Simonish();
    }


    private void initPanes() {
        //TODO
    }


    @Override
    public void actionPerformed(ActionEvent e) {
    }

    @Override
    public void mouseClicked(MouseEvent e) {    
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }
}

ScoreBoard Class

package components;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.Timer;

@SuppressWarnings({ "serial", "unused" })
public class ScoreBoard extends JPanel {
    private int score;
    private JLabel SimonNumberLabel;
    private JLabel timerLabel;
    private JButton resetBtn;


    public ScoreBoard(int bombsCnt,int w,int w2) {
        score = bombsCnt;
        SimonNumberLabel = new JLabel("Sequence Leingth: " + Integer.toString(bombsCnt), SwingConstants.CENTER);
        resetBtn = new JButton("reset");

        setBounds(0, 0, w*w2, 3*25);

        this.setLayout(new GridLayout(1,3));

        add(SimonNumberLabel);
        add(resetBtn);
    }

    public void AddScore(int update) {
        score += update;
        SimonNumberLabel.setText("Sequence Leingth: " + Integer.toString(score));
    }


    public JButton getResetBtn() {
        return resetBtn;
    }
}

SPane Class

package components;

import java.awt.Color;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;

@SuppressWarnings("serial")
public class SPane extends JPanel{

    Color C;
    Color DC;
    int x;
    int y;
    public SPane(int x, int y, int size, Color colorSwatch) {
        this();
        this.x = x;
        this.y = y;
        this.setLayout(new GridLayout(x+1,y+1));
        this.setBounds(x*size, y*size+75, size, size);
        C = colorSwatch;
        DC = C;
        DC = DC.darker();
        this.setBackground(DC);
        this.setVisible(true);
    }


    public SPane() {
        this.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
    }

    public void resetSPane() {
        // TODO Auto-generated method stub

    }

    public void pressPane()
    {
        this.setBackground(C);
        System.out.println("dsfdsfsdfsdf");
        try{
            Thread.sleep(1000);
        }catch (Exception e) {} 
        this.setBackground(DC);
    }

    public void clicked() {
        this.setBackground(Color.GREEN);
    }
}

1 个答案:

答案 0 :(得分:2)

这是第一个罪魁祸首......

private void PlaySequenc(){
    for(int i = 0 ; i < CurrentSequenceLeingth ; i++)
    {
        panBoard[Sequence[i]/2][Sequence[i]%2].pressPane();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {}
    }
}

这是从事件调度线程的内容中调用的,这阻止了它处理任何新更新或更新UI。

有关详细信息,请查看Concurrency in Swing并考虑使用Swing Timer,有关详细信息,请参阅How to use Swing Timers

pane.update(pane.getGraphics());在Swing中可以做的一些最糟糕的事情中排名非常非常高(Thread.sleep就在那里)。

看看Painting in AWT and SwingPerforming Custom Painting,了解绘画如何在Swing中运作

避免使用null布局,像素完美布局是现代ui设计中的一种幻觉。影响组件个体大小的因素太多,您无法控制。 Swing旨在与布局管理器一起工作,放弃这些将导致问题和问题的终结,您将花费越来越多的时间来纠正

您可能希望阅读Code Conventions for the Java TM Programming Language,这样可以让人们更轻松地阅读您的代码并让您阅读其他代码

例如......

所以,这个例子非常基本。它有三个按钮......

  • &#34;错误的方式&#34;,这基本上就是你正在做的事情
  • &#34;计时器方式&#34;,它使用Swing Timer
  • &#34;工作方式&#34;,使用SwingWorker

在您的情况下,我仍然认为Swing Timer是最佳选择,因为SwingWorker可以备份更新,一次全部吐出,这违背了你可能想要使用它的目的。

The Sequence

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Sequence {

    public static void main(String[] args) {
        new Sequence();
    }

    public Sequence() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<SequencePane> panels = new ArrayList<>(4);

        private Timer timer;
        private int sequenceIndex;

        public TestPane() {
            setLayout(new BorderLayout());
            Color colors[] = new Color[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW};
            for (int index = 0; index < 4; index++) {
                panels.add(new SequencePane(colors[index]));
            }
            JPanel content = new JPanel(new GridLayout(2, 2));
            for (SequencePane pane : panels) {
                content.add(pane);
            }

            add(content);

            JButton wrong = new JButton("The wrong way");
            JButton timerButton = new JButton("The Timer way");
            JButton workerButton = new JButton("The Worker way");

            JPanel actions = new JPanel();
            actions.add(wrong);
            actions.add(timerButton);
            actions.add(workerButton);

            add(actions, BorderLayout.SOUTH);

            wrong.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Collections.shuffle(panels);
                    for (SequencePane pane : panels) {
                        try {
                            pane.setHighlighted(true);
                            Thread.sleep(250);
                            pane.setHighlighted(false);
                        } catch (InterruptedException ex) {
                        }
                    }
                }
            });

            timer = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (sequenceIndex > 0) {
                        panels.get(sequenceIndex - 1).setHighlighted(false);
                    }

                    if (sequenceIndex < panels.size()) {
                        panels.get(sequenceIndex).setHighlighted(true);
                        sequenceIndex++;
                    } else {
                        timer.stop();
                        // All done, call some "play" method to begin playing
                    }
                }
            });

            timerButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    timer.stop();
                    Collections.shuffle(panels);
                    sequenceIndex = 0;
                    timer.start();
                }
            });

            SwingWorker worker = new SwingWorker<Object, SequenceState>() {
                @Override
                protected Object doInBackground() throws Exception {
                    for (SequencePane pane : panels) {
                        publish(new SequenceState(pane, true));
                        Thread.sleep(100);
                        publish(new SequenceState(pane, false));
                    }
                    return null;
                }

                @Override
                protected void process(List<SequenceState> chunks) {
                    SequenceState state = chunks.get(chunks.size() - 1);
                    state.applyState();
                }

                @Override
                protected void done() {
                    // Back in the EDT, call what ever "play" method you need
                }

            };

            workerButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Collections.shuffle(panels);
                    SequenceWorker worker = new SequenceWorker();
                    worker.execute();
                }
            });

        }

        public class SequenceWorker extends SwingWorker<Object, SequenceState> {
                @Override
                protected Object doInBackground() throws Exception {
                    for (SequencePane pane : panels) {
                        publish(new SequenceState(pane, true));
                        Thread.sleep(250);
                        publish(new SequenceState(pane, false));
                    }
                    return null;
                }

                @Override
                protected void process(List<SequenceState> chunks) {
                    for (SequenceState state : chunks) {
                        state.applyState();
                    }
                }

                @Override
                protected void done() {
                    // Back in the EDT, call what ever "play" method you need
                }

            }

        public class SequenceState {

            private SequencePane sequencePane;
            private boolean highlighted;

            public SequenceState(SequencePane sequencePane, boolean highlighted) {
                this.sequencePane = sequencePane;
                this.highlighted = highlighted;
            }

            public SequencePane getSequencePane() {
                return sequencePane;
            }

            public boolean isHighlighted() {
                return highlighted;
            }

            public void applyState() {
                getSequencePane().setHighlighted(isHighlighted());
            }
        }

    }

    public class SequencePane extends JPanel {

        private boolean highlighted;

        public SequencePane(Color color) {
            setOpaque(false);
            setBackground(color);
        }

        public void setHighlighted(boolean highlighted) {
            this.highlighted = highlighted;
            repaint();
        }

        public boolean isHighlighted() {
            return highlighted;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(50, 50);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (!isHighlighted()) {
                g2d.setComposite(AlphaComposite.SrcOver.derive(0.25f));
            }
            g2d.setColor(getBackground());
            g2d.fillRect(0, 0, getWidth(), getHeight());
            g2d.dispose();
        }

    }

}