
本文旨在帮助开发者解决Swing程序中`repaint()`方法调用后`paintComponent()`方法未被执行的问题。通过分析常见原因,例如线程问题和Swing的被动渲染机制,并提供使用`Swing Timer`的解决方案,确保UI更新在事件分发线程中进行,从而正确触发`paintComponent()`方法的执行,实现界面的动态更新。
在Swing开发中,repaint()方法用于请求组件重绘,而paintComponent()方法则负责实际的绘制工作。然而,有时开发者会遇到调用repaint()后paintComponent()方法并未被执行的情况,导致界面无法更新。这通常与Swing的线程模型和渲染机制有关。
理解Swing的线程模型
Swing是单线程的,这意味着所有的UI更新都应该在事件分发线程 (Event Dispatching Thread, EDT) 中进行。长时间运行或阻塞的操作不应在EDT中执行,否则会导致UI冻结。如果在非EDT线程中更新UI,可能会导致各种问题,包括paintComponent()方法不被调用。
Swing的被动渲染机制
Swing使用被动渲染引擎。开发者不能直接控制绘制过程,而需要遵循Swing的渲染流程。repaint()方法仅仅是向Swing请求重绘,Swing会在适当的时候调用paintComponent()方法。如果由于某些原因(例如线程问题)导致Swing无法正常调度重绘,paintComponent()方法就不会被执行。
解决方案:使用Swing Timer
解决repaint()不调用paintComponent()问题的常用方法是使用Swing Timer。Swing Timer会在EDT中定期触发事件,从而可以在EDT中安全地更新UI。
以下是一个使用Swing Timer的示例代码:
企业网站通用源码1.0
企业网站通用源码是以aspcms作为核心进行开发的asp企业网站源码。企业网站通用源码是一套界面设计非常漂亮的企业网站源码,是2016年下半年的又一力作,适合大部分的企业在制作网站是参考或使用,源码亲测完整可用,没有任何功能限制,程序内核使用的是aspcms,如果有不懂的地方或者有不会用的地方可以搜索aspcms的相关技术问题来解决。网站UI虽然不是特别细腻,但是网站整体格调非常立体,尤其是通观全
0 查看详情
import java.awt.Color;import java.awt.Dimension;import java.awt.EventQueue;import java.awt.Graphics;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_SCREEN_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("Updatey update"); repaint(); } public void paintComponent(final Graphics g) { super.paintComponent(g); System.out.println("Painty paint paint"); Graphics2D g2 = (Graphics2D) g.create(); g2.setColor(Color.white); g2.fillRect(100, 100, TILE_SIZE, TILE_SIZE); g2.dispose(); } }}
代码解释:
EventQueue.invokeLater(): 确保JFrame的创建和显示在EDT中进行。GamePane 类: 继承自JPanel,负责绘制矩形。Timer: Timer以5毫秒的间隔触发ActionListener。ActionListener.actionPerformed(): 在actionPerformed方法中调用update()方法。update(): 调用repaint()方法请求重绘。paintComponent(): 实际的绘制方法,绘制一个白色矩形。
通过使用Swing Timer,可以确保repaint()方法在EDT中被调用,从而正确触发paintComponent()方法的执行。
注意事项:
确保所有的UI更新操作都在EDT中进行。避免在EDT中执行耗时操作,可以使用SwingWorker来处理后台任务。理解Swing的渲染机制,遵循Swing的渲染流程。避免在一个JPanel中创建自己的JFrame,这通常不是一个好的设计。JPanel应该被添加到现有的JFrame中。
总结
解决Swing中repaint()不调用paintComponent()的问题,关键在于理解Swing的线程模型和渲染机制。通过使用Swing Timer,可以确保UI更新在EDT中进行,从而正确触发paintComponent()方法的执行。遵循Swing的最佳实践,可以避免许多常见的UI问题,并提高程序的稳定性和性能。
以上就是解决Swing中repaint()不调用paintComponent()的问题的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/719293.html
微信扫一扫
支付宝扫一扫