java问题1解决方法:repaint()(更新ing)

       不久前发的问题博客,绘制对象撤销的问题,前几天看到一个repaint()方法, 试了一下,棋盘是全部撤销了,也能够重新下了,但是也有了新问题:悔棋这一步骤做不下去了,主要是对repaint()方法的认识还不够,现在java学的还是初步吧,以后继续更新这篇博客。

       问题:http://blog.youkuaiyun.com/thehide/article/details/49804319

<pre name="code" class="java">if (is_win(i, j, chesses[i][j]))
{
    String str = (chesses[i][j] == 1 ? "黑子" : "白子") + "赢了!";
    JOptionPane.showMessageDialog(null, str);
    //将画出来的棋子撤销掉,接下来重置棋盘
    repaint();
    for(int t=0; t<12; t++)
    {
        for(int k=0; k<12; k++)
        {
            chesses[t][k]=0;
        }
    }
    flag_color = false;
    flag_begin = false;
}

 主要是repaint()方法的使用,其实并不会,督促学习!



<think> 我们已从引用中提取关键信息: 引用[1]和[3]明确指出错误原因:在paintEvent中重复创建QPainter对象且未正确结束,或者递归调用repaint。 引用[2]提到多线程刷新控件导致崩溃,错误信息同样是"Recursive repaint detected"。 结合之前回答,解决方案总结如下: 1. 确保在paintEvent中正确使用QPainter(避免重复创建且未销毁)。 2. 避免在paintEvent中调用update()repaint(),否则会导致递归重绘。 3. 多线程环境下,必须通过信号槽机制将界面更新请求发送到主线程执行。 现在针对用户问题,详细解答: </think> ### 解决 "QWidget::repaint: Recursive repaint detected" 错误的方法 #### 一、错误原因分析 此错误表示在 `paintEvent()` 函数中触发了新的重绘请求,形成了无限递归循环。主要发生在以下场景: 1. 在 `paintEvent()` 中直接调用 `update()` 或 `repaint()` 函数[^1][^2] 2. 多线程环境中多个线程同时请求界面刷新[^2] 3. `paintEvent()` 内频繁创建 `QPainter` 对象而未销毁[^3] #### 二、核心解决方案 ##### 1. 禁止在 `paintEvent()` 中触发重绘 ```cpp void MyWidget::paintEvent(QPaintEvent* event) { // 错误做法:会触发递归 // update(); QPainter painter(this); // ...绘制操作... } ``` ##### 2. 使用递归防护标志(推荐) ```cpp void MyWidget::paintEvent(QPaintEvent* event) { if (m_isPainting) return; // 阻止递归调用 m_isPainting = true; // 设置标记 QPainter painter(this); // ...绘制操作... m_isPainting = false; // 清除标记 } ``` ##### 3. 多线程环境安全更新 ```cpp // 工作线程中 emit updateRequested(); // 主窗口类 void MainWindow::handleUpdate() { if (!m_isPainting) { // 检查防护标志 update(); } } ``` #### 三、进阶修复技巧 ##### 1. 正确处理 `QPainter` 生命周期 ```cpp void MyWidget::paintEvent(QPaintEvent* event) { // 局部作用域自动管理资源 { QPainter painter(this); // 构造函数自动begin // ...绘制操作... } // 析构函数自动end } ``` ##### 2. 避免强制重绘 ```diff - repaint(); // 立即重绘(易导致递归) + update(); // 合并重绘请求(推荐) ``` ##### 3. 事件循环优化 ```cpp // 替代QApplication::processEvents() QTimer::singleShot(0, this, [=]{ update(); // 延迟到事件循环安全时执行 }); ``` #### 四、调试与验证 1. **日志追踪**:在 `paintEvent()` 入口添加日志,检测调用频率 2. **性能分析**:使用 `QElapsedTimer` 测量重绘耗时 3. **堆栈检查**:设置断点查看调用栈,定位额外重绘请求源 #### 五、典型场景解决方案 **多线程界面更新[^2]**: ```cpp // 工作线程 void WorkerThread::run() { while (true) { // ...处理数据... emit dataReady(result); // 通过信号通知主线程 } } // 主窗口 connect(worker, &WorkerThread::dataReady, this, [=](Data data){ if (!m_isPainting) { // 防护检查 m_displayData = data; update(); } }); ``` > **关键原则**:Qt 绘图系统是事件驱动模型,重绘请求应作为事件队列处理而非立即执行,避免在绘制过程中触发新绘制操作[^1][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值