以下代码示例让我对正在进行的项目感到悲伤:
这是我的问题......
此代码导致在窗口上绘制一个正方形网格,以及从该网格顶部开始的彩色形状:
MainWindow mainAppWindow = mainAppWindow = new MainWindow("TETRIS");
mainAppWindow.setExtendedState(Frame.MAXIMIZED_BOTH);
mainAppWindow.setVisible(true);
TetriminoFactory blockBuilder = mainAppWindow.getGameBoard().getBlockFactory();
mainAppWindow.getGameBoard().setActiveTetrimino(blockBuilder.createTetrimino());
Tetrimino activeTetrimino = mainAppWindow.getGameBoard().getActiveTetrimino();
在此之后,我有一个while循环,它应该每秒将屏幕上的形状移动指定的距离。这个动作应该在窗口上显示:
while((activeTetrimino.getLowermostPiece().getLoc().getYPos() / MiscConsts.TETRIS_UNIT) <= mainAppWindow.getGameBoard().getLowermostRowIndex())
{
if(activeTetrimino.checkForNeighbouringBlock().equals(Collision.BLOCK_BELOW_ME))
{
if(!activeTetrimino.setSecuredState(true))
{
activeTetrimino = blockBuilder.createTetrimino();
}
}
activeTetrimino.moveTetrimino(0, MiscConsts.TETRIS_UNIT);
mainAppWindow.canvas.repaint();
try {
Thread.sleep(MiscConsts.TIME_BETWEEN_ADVANCEMENTS);
} catch (InterruptedException e) {
System.out.println("ERROR - InterruptedException thrown in operate(). Terminating.");
e.printStackTrace();
System.exit(1000);
}
}
此时我遇到了一个问题。循环似乎撤消所有先前的绘图,并产生空白屏幕。如果我对循环进行注释,则会绘制网格以及形状,但当然不会发生移动。我不确定这里发生了什么,但我预感到它与线程或其他东西有关。或者也许只是while循环是反摆动:P
完成EXCERPT:
public static void main(String[] args)
{
theApp = new Tetris();
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
theApp.createGUI(); // Call GUI creator
}
});
}
public void createGUI()
{
MainWindow mainAppWindow = mainAppWindow = new MainWindow("TETRIS");
mainAppWindow.setExtendedState(Frame.MAXIMIZED_BOTH);
mainAppWindow.setVisible(true);
TetriminoFactory blockBuilder = mainAppWindow.getGameBoard().getBlockFactory();
// NEEDS WORK???
mainAppWindow.getGameBoard().setActiveTetrimino(blockBuilder.createTetrimino());
Tetrimino activeTetrimino = mainAppWindow.getGameBoard().getActiveTetrimino();
while((activeTetrimino.getLowermostPiece().getLoc().getYPos() / MiscConsts.TETRIS_UNIT) <= mainAppWindow.getGameBoard().getLowermostRowIndex())
{
if(activeTetrimino.checkForNeighbouringBlock().equals(Collision.BLOCK_BELOW_ME))
{
if(!activeTetrimino.setSecuredState(true))
{
activeTetrimino = blockBuilder.createTetrimino();
}
}
activeTetrimino.moveTetrimino(0, MiscConsts.TETRIS_UNIT);
mainAppWindow.canvas.repaint();
try {
Thread.sleep(MiscConsts.TIME_BETWEEN_ADVANCEMENTS);
} catch (InterruptedException e) {
System.out.println("ERROR - InterruptedException thrown in operate(). Terminating.");
e.printStackTrace();
System.exit(1000);
}
}
}
答案 0 :(得分:1)
看起来你试图在Event Dispatching Thread的上下文中执行循环。
除其他事项外,EDT负责处理重绘请求。这意味着如果你做任何阻止这个线程运行的东西,它就不能重新绘制屏幕,直到阻止它完成为止。这可以解释您的部分问题。
请查看Concurrency in Swing了解详情。
最简单的解决方案可能是用while
代替javax.swing.Timer
外观
例如......
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestBrick {
public static void main(String[] args) {
new TestBrick();
}
public TestBrick() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int yPos = 0;
public TestPane() {
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
yPos++;
if (yPos + 10 > getHeight()) {
yPos = 0;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int width = getWidth();
int xPos = (width - 10) / 2;
g.drawRect(xPos, yPos, 10, 10);
}
}
}
答案 1 :(得分:1)
您在事件发送线程或简称EDT上呼叫Thread.sleep
。
EDT是挥杆完成所有工作的地方。如果你让它进入睡眠状态,那么Swing将不会进行任何绘画或处理任何用户输入。
一种解决方案是将while循环的主体放入SwingTimer,每秒运行一次。
另一个更复杂的解决方案是使用具有自己的绘图上下文的awt画布,并且可以在不同的线程中绘制并在该线程中运行循环。如果您想采用画布方法,请查看Active Rendering in Java上的 Gamedev的文章。