Java Button暂停图形更新
作者:互联网
所以我有一个班级,我必须制作一个程序来制作西蒙.
我知道我这样做的方式不一定是最好的方式,但是,他有一些模糊的要求,所以这就是我这样做的原因.
我的程序即将完成,但我有一个主要问题.
当我按下重置按钮时,我调用一个名为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) {}
}
}
这是从Event Dispatching Thread的内容中调用的,这阻止了它处理任何新更新或更新UI.
有关更多详细信息,请查看Concurrency in Swing并考虑使用Swing Timer,有关详细信息,请参阅How to use Swing Timers
pane.update(pane.getGraphics());在Swing中你可以做的一些最糟糕的事情中排名非常非常高(Thread.sleep就在那里).
看看Painting in AWT and Swing和Performing Custom Painting,了解绘画在Swing中的作用
避免使用空布局,像素完美布局是现代ui设计中的错觉.影响组件个体大小的因素太多,您无法控制. Swing旨在与布局管理器一起工作,放弃这些将导致问题和问题的结束,您将花费越来越多的时间来纠正
您可能希望阅读Code Conventions for the Java TM Programming Language,这将使人们更容易阅读您的代码并让您阅读其他代码
例如…
所以,这个例子非常基本.它有三个按钮……
>“错误的方式”,这基本上就是你正在做的事情
>“定时器方式”,使用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<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();
}
}
}
标签:thread-sleep,java,swing 来源: https://codeday.me/bug/20190926/1820137.html