我正在编写一个程序来绘制一条在屏幕上移动的火车。我正在使用带有fillRect,drawOval和draw lines方法的图形类。我有一个按钮,可以在屏幕的右侧启动火车。在屏幕消失后,它应该随机y位置重新出现并再次运行。这应该循环直到单击停止按钮。问题是我正在使用thread.sleep()方法在更新列车位置之前暂停程序。出于某种原因,我无法在程序运行时单击任何按钮。有关如何使我的停止按钮工作的任何想法?感谢。
这是我正在使用的代码。它还具有JFrame表单在netbeans中的常规代码。
private void btnStartTrainActionPerformed(java.awt.event.ActionEvent evt) {
run = true;
while (run) {
Graphics g = jPanel1.getGraphics();
int x =0;
int y = (int)(Math.random() *500) + 20;
int smoke =1;
for( x = 900; x > -600; x--)
{
drawTrain(g, x, y, smoke);
try {
Thread.sleep(17);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
clearJFrame(g);
smoke++;
x = x-4;
}
if (x == -599)
{
x = 900;
y = (int)(Math.random() *500) + 20;
}
}
}
private void btnStopTrainActionPerformed(java.awt.event.ActionEvent evt) {
run = false;
}
public void drawTrain(Graphics g, int x, int y, int smoke)
{
// draw locomotive
g.setColor(Color.RED);
g.fillRect(x, y, 100, 30);
g.fillRect(x +100, y-30, 40, 60);
g.setColor(Color.BLACK);
g.fillRect(x +110, y-20, 20, 10);
g.drawLine(x +10, y, x, y-20);
g.drawLine(x +11, y, x, y-20);
g.drawLine(x, y-20, x +30, y-20);
g.drawLine(x +30, y-20, x +20, y);
g.drawLine(x +31, y-20, x +20, y);
g.drawLine(x, y+30, x-20, y+25);
g.drawLine(x-20, y+25, x-20, y+20);
g.drawLine(x-20, y+20, x, y+15);
g.drawOval(x +10, y+20, 25, 25); //draw wheels
g.drawOval(x +35, y+20, 25, 25);
g.drawOval(x +60, y+20, 25, 25);
g.drawOval(x +85, y+20, 25, 25);
g.drawOval(x +110, y+20, 25, 25);
if (smoke >20)
g.drawOval(x +8, y-33, 12, 12); // draw smoke
if (smoke >40)
g.drawOval(x +12, y-53, 12, 12);
if (smoke >60)
g.drawOval(x +18, y-73, 13, 13);
if (smoke >80)
g.drawOval(x +25, y-100, 14, 14);
if(smoke >100)
g.drawOval(x+31, y-120, 15, 15);
if (smoke > 120)
g.drawOval(x+37, y - 140, 16, 16);
if (smoke > 140)
g.drawOval(x+44, y-160, 17, 17);
g.setColor(Color.RED);
g.fillRect(x +160, y, 80, 30); // draw additional cars
g.fillRect(x +260, y, 80, 30);
g.fillRect(x +360, y, 80, 30);
g.setColor(Color.BLACK);
g.drawOval(x +160, y+20, 25, 25);
g.drawOval(x +215, y+20, 25, 25);
g.drawOval(x +260, y+20, 25, 25);
g.drawOval(x +315, y+20, 25, 25);
g.drawOval(x +360, y+20, 25, 25);
g.drawOval(x +415, y+20, 25, 25);
}
public void clearJFrame(Graphics g)
{
g.setColor(jPanel1.getBackground());
g.fillRect(0, 0, jPanel1.getWidth(), jPanel1.getHeight());
}
答案 0 :(得分:3)
您正在事件调度线程上执行Thread.sleep()
,使GUI在整个调用期间冻结。
延迟在GUI上执行操作的正确方法是使用Swing Timer安排它。
答案 1 :(得分:2)
当Swing程序需要执行长时间运行的任务时,您需要使用SwingWorker。阻止事件调度线程将冻结您的GUI。
从oracle阅读这两个教程,你就会知道应该做什么:
答案 2 :(得分:0)
不幸的是,当您使用 Swing (以及几乎每个UI框架)时,您无法像在UI线程中那样进行睡眠(也称为事件调度线程),因为,它真的是这个管理整个UI的线程。所以,通过睡觉它是正常的,它对整个睡眠时间没有反应。
你应该做的是从btnStartTrainActionPerformed
启动另一个线程,然后在这个线程中进行休眠。
类似的东西:
private void btnStartTrainActionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread() {
public void run()
{
run = true;
while (run)
{
Graphics g = jPanel1.getGraphics();
int x =0;
int y = (int)(Math.random() *500) + 20;
int smoke =1;
for( x = 900; x > -600; x--)
{
// Needed to make this change back on the UI Thread
SwingUtilities.invokeLater(new Runnable() {
public void run() {
drawTrain(g, x, y, smoke);
}
});
try
{
Thread.sleep(17);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
clearJFrame(g);
smoke++;
x = x-4;
}
if (x == -599)
{
x = 900;
y = (int)(Math.random() *500) + 20;
}
}
}
};
thread.start();
}