Java按钮暂停图形更新

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

我的程序即将完成,但我有一个主要问题。 当我按下重置按钮时,我调用一个名为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类

 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类

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

这是第一个罪魁祸首……

 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。

有关更多详细信息,请参阅Swing中的Concurrency,并考虑使用Swing Timer ,有关详细信息,请参阅如何使用Swing Timers

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

看看AWT中的绘画和摇摆和表演自定义绘画 ,了解绘画如何在Swing中起作用

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

您可能希望阅读Java TM编程语言的代码约定 ,它将使人们更容易阅读您的代码并让您阅读其他代码

例如...

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

  • “错误的方式”,这基本上就是你正在做的事情
  • “定时器方式”,使用Swing Timer
  • “工作方式”,使用SwingWorker

在你的情况下,我仍然认为Swing Timer是最好的选择,因为SwingWorker可能会备份更新,立即将它们全部吐出,这就失去了为什么你可能想要使用它的目的。

序列

 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 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() { @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 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 { @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 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(); } } }