0

0

解决Swing中repaint()不调用paintComponent()的问题

霞舞

霞舞

发布时间:2025-10-24 09:56:01

|

624人浏览过

|

来源于php中文网

原创

解决swing中repaint()不调用paintcomponent()的问题

本文旨在帮助开发者解决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的示例代码:

行业贸易网站管理系统 2007 Beta 1
行业贸易网站管理系统 2007 Beta 1

1.修正BUG站用资源问题,优化程序2.增加关键词搜索3.修改报价4.修正BUG 水印问题5.修改上传方式6.彻底整合论坛,实现一站通7.彻底解决群发垃圾信息问题。注册会员等发垃圾邮件7.彻底解决数据库安全9.修改交易方式.增加网站担保,和直接交易两中10.全站可选生成html.和单独新闻生成html(需要装组建)11. 网站有10中颜色选择适合不同的行业不同的颜色12.修改竞价格排名方式13.修

下载
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();
        }
    }
}

代码解释:

  1. EventQueue.invokeLater(): 确保JFrame的创建和显示在EDT中进行。
  2. GamePane 类: 继承自JPanel,负责绘制矩形。
  3. Timer: Timer以5毫秒的间隔触发ActionListener。
  4. ActionListener.actionPerformed(): 在actionPerformed方法中调用update()方法。
  5. update(): 调用repaint()方法请求重绘。
  6. 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问题,并提高程序的稳定性和性能。

相关文章

Windows激活工具
Windows激活工具

Windows激活工具是正版认证的激活工具,永久激活,一键解决windows许可证即将过期。可激活win7系统、win8.1系统、win10系统、win11系统。下载后先看完视频激活教程,再进行操作,100%激活成功。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

481

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

61

2025.12.01

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

23

2026.01.19

java用途介绍
java用途介绍

本专题整合了java用途功能相关介绍,阅读专题下面的文章了解更多详细内容。

11

2026.01.19

java输出数组相关教程
java输出数组相关教程

本专题整合了java输出数组相关教程,阅读专题下面的文章了解更多详细内容。

3

2026.01.19

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

2

2026.01.19

xml格式相关教程
xml格式相关教程

本专题整合了xml格式相关教程汇总,阅读专题下面的文章了解更多详细内容。

4

2026.01.19

PHP WebSocket 实时通信开发
PHP WebSocket 实时通信开发

本专题系统讲解 PHP 在实时通信与长连接场景中的应用实践,涵盖 WebSocket 协议原理、服务端连接管理、消息推送机制、心跳检测、断线重连以及与前端的实时交互实现。通过聊天系统、实时通知等案例,帮助开发者掌握 使用 PHP 构建实时通信与推送服务的完整开发流程,适用于即时消息与高互动性应用场景。

13

2026.01.19

微信聊天记录删除恢复导出教程汇总
微信聊天记录删除恢复导出教程汇总

本专题整合了微信聊天记录相关教程大全,阅读专题下面的文章了解更多详细内容。

93

2026.01.18

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.7万人学习

C# 教程
C# 教程

共94课时 | 7.1万人学习

Java 教程
Java 教程

共578课时 | 47.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号