// ============================================================================ // mandelbrot_widget —— Day4 Mandelbrot 渲染器的交互与渲染调度主体(QWidget) // 职责: // * paintEvent : 把累积 QImage 一次性画到窗口(QPainter 绘图知识点) // * wheelEvent/mouse* : 滚轮缩放(以鼠标为锚)、左键拖拽平移(事件处理知识点) // * scheduleRender() : 切水平条带丢 QThreadPool 并行算(多线程知识点) // * onStripReady() : 收条带、拼图、版本号防过期、耗时显示 // * onRenderOnMainThread() : 「主线程渲染」按钮——同步算整帧,演示事件循环被 // 占用即界面冻结(直击 Day4 slides「主线程耗时=冻结」痛点) // * onToggleThreadMode() : 复用同一套分块逻辑,切线程池大小,对比单/多线程加速比 // ============================================================================ #ifndef MANDELBROT_WIDGET_H #define MANDELBROT_WIDGET_H #include #include #include #include #include "mandelbrot_strip_task.h" // MandelViewport / MandelPalette class QLabel; class MandelbrotWidget : public QWidget { Q_OBJECT public: explicit MandelbrotWidget(QWidget* parent = nullptr); protected: void paintEvent(QPaintEvent*) override; void wheelEvent(QWheelEvent*) override; void mousePressEvent(QMouseEvent*) override; void mouseMoveEvent(QMouseEvent*) override; void mouseReleaseEvent(QMouseEvent*) override; void resizeEvent(QResizeEvent*) override; private slots: void onStripReady(quint64 epoch, int stripIndex, QImage strip); void onRenderOnMainThread(); // 卡死演示 void onToggleThreadMode(); // 单/多线程切换 private: void scheduleRender(); // ++epoch + 分块丢池 MandelViewport vp_; MandelPalette pal_; QImage pixmap_; // 累积画布(离屏 QImage,paintEvent 外对它构造 QPainter 合法) quint64 epoch_ = 0; // 渲染版本号:新视口令旧结果作废丢弃(防过期覆盖) int stripsTotal_ = 0; int stripsDone_ = 0; QElapsedTimer timer_; bool multiThread_ = true; int threadCount_ = 0; bool dragging_ = false; QPoint lastMouse_; QLabel* label_ = nullptr; }; #endif // MANDELBROT_WIDGET_H