在JFrame Java中闪烁
大家好我正在做一个线程来更新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
。 此类允许您定期对事件调度线程执行操作。
- Swing
Timer
教程 - 在SO上发布的动画示例 (在Swt wiki中链接在SO btw上)
一些一般规则
- Swing不是线程安全的,您应该只在Event Dispatching Thread的上下文中更新UI组件。
- 您不会控制绘制过程,重绘管理器会这样做。 您可以通过调用
repaint
来请求更新,但在尝试更新显示时,不应直接调用update
和paint
。 - paint子系统使用的
Graphics
上下文是一个共享资源,并且不保证在绘制周期之间是相同的,您永远不应该保持对它的引用。 您也不应该依赖于JComponent#getGraphics
的结果,此方法能够返回null。
示例解决方案
您有很多选择,具体取决于您最终要实现的目标。
您可以使用SwingWorker
,但考虑到您要进入无限循环的事实并且使用SwingUtilities#invokeLater
更容易然后实际使用publish
方法,这种方法实际上会更多。
您也可以使用Thread
,但最终会遇到与使用SwingWorker
相同的问题
对于您所呈现的内容,simpliset解决方案实际上是一个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中执行长时间运行的任务,那么您也会遇到问题。
查看这篇文章,了解有关GUI Threading in Java
更多信息
- 结果集未打开。 validation自动提交是否关闭。 Apache Debry
- Spring数据mongodb查询自动将String转换为ObjectId
- 如何将元素的内部文本内容映射到Class属性?
- 如何在Java中实现基于线程的UDP服务器?
- 为什么阿拉伯字母没有插入数据库?
- 这会给128位哈希吗?
- 如何使用Java EE 7和Glassfish 4在IntelliJ IDEA Community Edition中创建Java Servlet应用程序?
- 从Java / C#到C ++的最佳方法是什么?
- 有什么区别:使用JPA @TableGenerator的序列ID,@ GeneratedValue与数据库Auto_Increment