painter为什么画不出来 repaint没有执行怎么回事
Timer 的解决方案,确保 UI 的正确更新和渲染。我们将深入探讨 Swing 的线程安全和被动渲染机制,并通过代码示例展示如何避免常见错误并实现流畅的动画效果。
在 Swing 应用程序开发中,repaint() 和 paintComponent() 方法是实现自定义绘制和动画效果的关键。然而,初学者经常会遇到调用 paintComponent() 后 repaint() 未执行的问题(Dispatching Thread)
Swing 是单线程的,这意味着所有 UI 更新都应该在一个线程(EDT)上执行。长时间运行或在 EDT 上阻塞操作会导致 UI 卡顿。因此,避免在 EDT 上运行非常重要。依赖于状态会导致不可预测的结果。Swing 的动态渲染机制
Swing 使用动态渲染引擎。这意味着您无法直接控制绘画过程。相反,您需要通过调用 repaint() 来请求重绘,Swing 系统会在适当的时候调用 paintComponent() 方法。解决方案:使用 Swing Timer
解决 repaint() 不调用 paintComponent() 问题的常用方法是使用 javax.swing.Timer。Timer 类允许您在 EDT 上以指定的时间间隔执行代码。这可以确保 UI 更新是线程安全的,并且不会阻塞 EDT。
AI建造知识
用人工智能ChatGPT帮你解答所有建造问题 22 查看详情
以下是使用Swing Timer的示例: import java.awt.Color;import java.awt.Dimension;import java.awt.EventQueue;import java.awt.Graphics2D;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.Timer;public class Main { public static void main(String[] args) { new Main(); } public Main() { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame frame = new JFrame(); frame.add(new GamePane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class GamePane extends JPanel { final int ORIGINAL_TILE_SIZE = 16; final int SCALE = 3; final int TILE_SIZE = ORIGINAL_TILE_SIZE * SCALE; final int MAX_SCREEN_COLUMNS = 16; final int MAX_SCALE
REEN_ROWS = 12; final int SCREEN_WIDTH = TILE_SIZE * MAX_SCREEN_COLUMNS; final int SCREEN_HEIGHT = TILE_SIZE * MAX_SCREEN_ROWS; private Timer timer; @Override public Dimension getPreferredSize() { return new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT); } @Override public void addNotify() { super.addNotify(); if (timer != null) { timer.stop(); } timer = new Timer(5, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { update(); } }); timer.start(); } @Override public void removeNotify() { super.removeNotify(); if (timer != null) { timer.stop(); } } public void update() { System.out.println(quot;Updatey updatequot;); repaint(); } public void paintComponent(final Graphics g) { super.paintComponent(g); System.out.println(quot;Painty paint paintquot;); Graphics2D g2 = (Graphics2D) g.create(); g2.setColor(Color.white); g2.fillRect(100, 100, TILE_SIZE, TILE_SIZE); g2.dispose(); } } } 复制后登录
本例中Timer以5毫秒的间隔触发ActionListener,进而调用update()方法。
update()方法,然后调用repaint(),这会触发paintComponent()方法。
代码说明: EventQueue.invokeLater(...): 确保JFrame的创建并显示在EDT上。 GamePane类继承自JPanel,负责绘制内容。 getPreferredSize(): 设置JFrame的首次选择大小,确保JFrame能够正确显示。 当JPanel从容器中移除时调用,Timer在此停止。 Timer timer = new Timer(5, ...): 创建一个Timer,每5毫秒触发一次ActionListener。 update(): 更新游戏逻辑,并调用repaint()请求重绘。 paintComponent(): 执行实际的绘制操作。 注意不要阻塞EDT: 避免在EDT上执行操作。 需要更新UI时才调用repaint(),Swing系统会处理实际的重绘过程。释放资源:在 paintComponent() 方法中,使用 g.create() 创建 Graphics2D 对象,然后使用 g2.dispose() 释放资源。总结
理解 Swing 的线程模型和渲染机制是编写 Swing 应用程序的关键。通过使用 Swing Timer 并遵循线程安全最佳实践,您可以避免 repaint() 调用 paintComponent() 的问题,并创建流畅的动画效果。请记住,始终在 EDT 上执行 UI 更新,并避免阻塞 EDT。
以上就是repaint()方法不调用paintComponent()问题的解决方案。详细内容,更多请关注其他相关文章! Java:正生名理电影电影的公司的公司之之之和可以下载的多文件地学
