大家好,我正在做一个线程来通过 JFrame 更新球,所以我重新绘制屏幕...然后绘制球更新其位置..然后再次绘制屏幕...绘制球并进行相同的循环.. .这是代码
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
Thread t = new Thread()
{
public void run()
{
while(true)
{
repaint();
b2.update(ob,2);
b2.paint(ob.getGraphics());
b2.setT(b2.getT() + 1);
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
System.out.println("Error in Sleeping");
}
}
}
};
t.start();
}
但问题是我看不到球...屏幕的油漆总是覆盖球,而球就像在 Jframe 下方 ..
如果您想在 Swing 中添加动画,推荐使用的类是
javax.swing.Timer
。该类允许您定期对事件调度线程执行操作。
Timer
教程一些一般规则
repaint
来请求更新,但在尝试更新显示时切勿直接调用 update
和 paint
。Graphics
上下文是共享资源,不能保证在绘制周期之间相同,您永远不应该维护对它的引用。您也不应该依赖 JComponent#getGraphics
的结果,此方法能够返回 null。示例解决方案
您有多种选择,具体取决于您最终想要实现的目标。
你可以使用
SwingWorker
,但考虑到你要做的就是进入无限循环,使用 SwingUtilities#invokeLater
会更容易,而不是实际使用 publish
方法,因此,这种方法实际上会更多工作。
您也可以使用
Thread
,但最终会遇到与使用 SwingWorker
相同的问题
对于您所提出的,最简单的解决方案实际上是一个
javax.swing.Timer
public class Blinky {
public static void main(String[] args) {
new Blinky();
}
public Blinky() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BlinkyPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected class BlinkyPane extends JPanel {
private JLabel blinkyLabel;
private boolean blink = false;
public BlinkyPane() {
setLayout(new GridBagLayout());
blinkyLabel = new JLabel("I'm blinking here");
blinkyLabel.setBackground(Color.RED);
add(blinkyLabel);
Timer timer = new Timer(250, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
blink = !blink;
if (blink) {
blinkyLabel.setForeground(Color.YELLOW);
} else {
blinkyLabel.setForeground(Color.BLACK);
}
blinkyLabel.setOpaque(blink);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 100);
}
}
}
您可以查看 Swing Timer 和 Swing 中的并发 了解更多信息
如果您在 EDT(事件调度线程)之外访问 GUI 组件,那么您可能会遇到奇怪的问题,相反,如果您在 EDT 中执行长时间运行的任务,那么您也会遇到问题。
查看 this 帖子以了解有关
GUI Threading in Java
的更多信息