Scribble 示例演示如何重新实现某些 的事件处理程序,以接收为应用程序的小部件生成的事件。
我们重新实现鼠标事件处理程序以实现绘图,重新实现绘制事件处理程序以更新应用程序,重新实现调整大小事件处理程序以优化应用程序的外观。此外,我们重新实现 close 事件处理程序,以便在终止应用程序之前拦截 close 事件。
该示例还演示了如何使用实时绘制图像,以及重新绘制小部件。
使用涂鸦应用程序,用户可以绘制图像。该菜单使用户可以打开和编辑现有图像文件,保存图像并退出应用程序。绘图时,菜单允许用户选择笔颜色和笔宽,以及清除屏幕。此外,该菜单还为用户提供了有关Scribble示例以及一般Qt的信息。
该示例由两个类组成:
ScribbleArea
是一个自定义小部件,显示并允许用户在其上绘制。MainWindow
在 上方提供了一个菜单。ScribbleArea
我们将从复习课程开始。然后我们将回顾该类,该类使用 .ScribbleArea
MainWindow
ScribbleArea
涂鸦区域类定义
<span style="color:#404244"><span style="background-color:#3a4055"><span style="color:#ffffff"><span style="color:#ffff55">class</span> <span style="color:#4f9d08">ScribbleArea</span> <span style="color:#ffffff">:</span> <span style="color:#ffff55">public</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qwidget.html" href="https://doc.qt.io/qt-6/qwidget.html"><span style="color:#21be2b">QWidget</span></a>
<span style="color:#ffffff">{</span><span style="color:#ffffff">
Q_OBJECT
</span><span style="color:#ffff55">public</span><span style="color:#ffffff">:</span>
<span style="color:#4f9d08">ScribbleArea</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qwidget.html" href="https://doc.qt.io/qt-6/qwidget.html"><span style="color:#21be2b">QWidget</span></a> <span style="color:#ffffff">*</span><span style="color:#ffffff">parent </span><span style="color:#ffffff">=</span> <span style="color:#ffff55">nullptr</span><span style="color:#ffffff">);</span>
<span style="color:#ffff55">bool</span><span style="color:#ffffff"> openImage</span><span style="color:#ffffff">(</span><span style="color:#ffff55">const</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qstring.html" href="https://doc.qt.io/qt-6/qstring.html"><span style="color:#21be2b">QString</span></a> <span style="color:#ffffff">&</span><span style="color:#ffffff">fileName</span><span style="color:#ffffff">);</span>
<span style="color:#ffff55">bool</span><span style="color:#ffffff"> saveImage</span><span style="color:#ffffff">(</span><span style="color:#ffff55">const</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qstring.html" href="https://doc.qt.io/qt-6/qstring.html"><span style="color:#21be2b">QString</span></a> <span style="color:#ffffff">&</span><span style="color:#ffffff">fileName</span><span style="color:#ffffff">,</span> <span style="color:#ffff55">const</span> <span style="color:#ffff55">char</span> <span style="color:#ffffff">*</span><span style="color:#ffffff">fileFormat</span><span style="color:#ffffff">);</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> setPenColor</span><span style="color:#ffffff">(</span><span style="color:#ffff55">const</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qcolor.html" href="https://doc.qt.io/qt-6/qcolor.html"><span style="color:#21be2b">QColor</span></a> <span style="color:#ffffff">&</span><span style="color:#ffffff">newColor</span><span style="color:#ffffff">);</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> setPenWidth</span><span style="color:#ffffff">(</span><span style="color:#ffff55">int</span><span style="color:#ffffff"> newWidth</span><span style="color:#ffffff">);</span>
<span style="color:#ffff55">bool</span><span style="color:#ffffff"> isModified</span><span style="color:#ffffff">()</span> <span style="color:#ffff55">const</span> <span style="color:#ffffff">{</span> <span style="color:#ffff55">return</span><span style="color:#ffffff"> modified</span><span style="color:#ffffff">;</span> <span style="color:#ffffff">}</span>
<a data-cke-saved-href="https://doc.qt.io/qt-6/qcolor.html" href="https://doc.qt.io/qt-6/qcolor.html"><span style="color:#21be2b">QColor</span></a><span style="color:#ffffff"> penColor</span><span style="color:#ffffff">()</span> <span style="color:#ffff55">const</span> <span style="color:#ffffff">{</span> <span style="color:#ffff55">return</span><span style="color:#ffffff"> myPenColor</span><span style="color:#ffffff">;</span> <span style="color:#ffffff">}</span>
<span style="color:#ffff55">int</span><span style="color:#ffffff"> penWidth</span><span style="color:#ffffff">()</span> <span style="color:#ffff55">const</span> <span style="color:#ffffff">{</span> <span style="color:#ffff55">return</span><span style="color:#ffffff"> myPenWidth</span><span style="color:#ffffff">;</span> <span style="color:#ffffff">}</span>
<span style="color:#ffff55">public</span> <span style="color:#ffffff">slots</span><span style="color:#ffffff">:</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> clearImage</span><span style="color:#ffffff">();</span>
<span style="color:#ffff55">void</span> <span style="color:#ffff55">print</span><span style="color:#ffffff">();</span>
<span style="color:#ffff55">protected</span><span style="color:#ffffff">:</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> mousePressEvent</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qmouseevent.html" href="https://doc.qt.io/qt-6/qmouseevent.html"><span style="color:#21be2b">QMouseEvent</span></a> <span style="color:#ffffff">*</span><span style="color:#ffff55">event</span><span style="color:#ffffff">)</span> <span style="color:#ffff55">override</span><span style="color:#ffffff">;</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> mouseMoveEvent</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qmouseevent.html" href="https://doc.qt.io/qt-6/qmouseevent.html"><span style="color:#21be2b">QMouseEvent</span></a> <span style="color:#ffffff">*</span><span style="color:#ffff55">event</span><span style="color:#ffffff">)</span> <span style="color:#ffff55">override</span><span style="color:#ffffff">;</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> mouseReleaseEvent</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qmouseevent.html" href="https://doc.qt.io/qt-6/qmouseevent.html"><span style="color:#21be2b">QMouseEvent</span></a> <span style="color:#ffffff">*</span><span style="color:#ffff55">event</span><span style="color:#ffffff">)</span> <span style="color:#ffff55">override</span><span style="color:#ffffff">;</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> paintEvent</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qpaintevent.html" href="https://doc.qt.io/qt-6/qpaintevent.html"><span style="color:#21be2b">QPaintEvent</span></a> <span style="color:#ffffff">*</span><span style="color:#ffff55">event</span><span style="color:#ffffff">)</span> <span style="color:#ffff55">override</span><span style="color:#ffffff">;</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> resizeEvent</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qresizeevent.html" href="https://doc.qt.io/qt-6/qresizeevent.html"><span style="color:#21be2b">QResizeEvent</span></a> <span style="color:#ffffff">*</span><span style="color:#ffff55">event</span><span style="color:#ffffff">)</span> <span style="color:#ffff55">override</span><span style="color:#ffffff">;</span>
<span style="color:#ffff55">private</span><span style="color:#ffffff">:</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> drawLineTo</span><span style="color:#ffffff">(</span><span style="color:#ffff55">const</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qpoint.html" href="https://doc.qt.io/qt-6/qpoint.html"><span style="color:#21be2b">QPoint</span></a> <span style="color:#ffffff">&</span><span style="color:#ffffff">endPoint</span><span style="color:#ffffff">);</span>
<span style="color:#ffff55">void</span><span style="color:#ffffff"> resizeImage</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qimage.html" href="https://doc.qt.io/qt-6/qimage.html"><span style="color:#21be2b">QImage</span></a> <span style="color:#ffffff">*</span><span style="color:#ffffff">image</span><span style="color:#ffffff">,</span> <span style="color:#ffff55">const</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qsize.html" href="https://doc.qt.io/qt-6/qsize.html"><span style="color:#21be2b">QSize</span></a> <span style="color:#ffffff">&</span><span style="color:#ffffff">newSize</span><span style="color:#ffffff">);</span>
<span style="color:#ffff55">bool</span><span style="color:#ffffff"> modified </span><span style="color:#ffffff">=</span> <span style="color:#ffff55">false</span><span style="color:#ffffff">;</span>
<span style="color:#ffff55">bool</span><span style="color:#ffffff"> scribbling </span><span style="color:#ffffff">=</span> <span style="color:#ffff55">false</span><span style="color:#ffffff">;</span>
<span style="color:#ffff55">int</span><span style="color:#ffffff"> myPenWidth </span><span style="color:#ffffff">=</span> <span style="color:#ff55ff">1</span><span style="color:#ffffff">;</span>
<a data-cke-saved-href="https://doc.qt.io/qt-6/qcolor.html" href="https://doc.qt.io/qt-6/qcolor.html"><span style="color:#21be2b">QColor</span></a><span style="color:#ffffff"> myPenColor </span><span style="color:#ffffff">=</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qt.html" href="https://doc.qt.io/qt-6/qt.html"><span style="color:#21be2b">Qt</span></a><span style="color:#ffffff">::</span><span style="color:#ffffff">blue</span><span style="color:#ffffff">;</span>
<a data-cke-saved-href="https://doc.qt.io/qt-6/qimage.html" href="https://doc.qt.io/qt-6/qimage.html"><span style="color:#21be2b">QImage</span></a><span style="color:#ffffff"> image</span><span style="color:#ffffff">;</span>
<a data-cke-saved-href="https://doc.qt.io/qt-6/qpoint.html" href="https://doc.qt.io/qt-6/qpoint.html"><span style="color:#21be2b">QPoint</span></a><span style="color:#ffffff"> lastPoint</span><span style="color:#ffffff">;</span>
<span style="color:#ffffff">};</span></span></span></span>
该类继承自 。我们重新实现 和 函数来实现绘图。我们重新实现函数以更新涂鸦区域,并重新实现函数以确保我们绘制的函数在任何时候至少与小部件一样大。ScribbleArea
mousePressEvent()
mouseMoveEvent()
mouseReleaseEvent()
paintEvent()
resizeEvent()
我们需要几个公共函数:将图像从文件加载到涂鸦区域,允许用户编辑图像; 将当前显示的图像写入文件; 插槽清除涂鸦区域中显示的图像。我们需要私有函数来实际绘制,并更改 .插槽处理打印。openImage()
save()
clearImage()
drawLineTo()
resizeImage()
print()
我们还需要以下私有变量:
modified
是涂鸦区域中显示的图像是否有未保存的更改。true
scribbling
当用户在涂鸦区域内按鼠标左键时。true
penWidth
并按住应用程序中使用的笔的当前设置的宽度和颜色。penColor
image
存储用户绘制的图像。lastPoint
在上次按下鼠标或鼠标移动事件时保持光标的位置。
涂鸦区域类实现
<span style="color:#404244"><span style="background-color:#3a4055"><span style="color:#ffffff"><span style="color:#4f9d08">ScribbleArea</span><span style="color:#ffffff">::</span><span style="color:#4f9d08">ScribbleArea</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qwidget.html" href="https://doc.qt.io/qt-6/qwidget.html"><span style="color:#21be2b">QWidget</span></a> <span style="color:#ffffff">*</span><span style="color:#ffffff">parent</span><span style="color:#ffffff">)</span>
<span style="color:#ffffff">:</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qwidget.html" href="https://doc.qt.io/qt-6/qwidget.html"><span style="color:#21be2b">QWidget</span></a><span style="color:#ffffff">(</span><span style="color:#ffffff">parent</span><span style="color:#ffffff">)</span>
<span style="color:#ffffff">{</span><span style="color:#ffffff">
setAttribute</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qt.html" href="https://doc.qt.io/qt-6/qt.html"><span style="color:#21be2b">Qt</span></a><span style="color:#ffffff">::</span><span style="color:#ffffff">WA_StaticContents</span><span style="color:#ffffff">);</span>
<span style="color:#ffffff">}</span></span></span></span>
在构造函数中,我们设置了小部件的属性,指示小部件内容根植于左上角,并且在调整小部件大小时不会更改。Qt使用此属性来优化调整大小时的绘画事件。这纯粹是一种优化,只应用于内容是静态的并且根植于左上角的小部件。
<span style="color:#404244"><span style="background-color:#3a4055"><span style="color:#ffffff"><span style="color:#ffff55">bool</span> <span style="color:#4f9d08">ScribbleArea</span><span style="color:#ffffff">::</span><span style="color:#ffffff">openImage</span><span style="color:#ffffff">(</span><span style="color:#ffff55">const</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qstring.html" href="https://doc.qt.io/qt-6/qstring.html"><span style="color:#21be2b">QString</span></a> <span style="color:#ffffff">&</span><span style="color:#ffffff">fileName</span><span style="color:#ffffff">)</span>
<span style="color:#ffffff">{</span>
<a data-cke-saved-href="https://doc.qt.io/qt-6/qimage.html" href="https://doc.qt.io/qt-6/qimage.html"><span style="color:#21be2b">QImage</span></a><span style="color:#ffffff"> loadedImage</span><span style="color:#ffffff">;</span>
<span style="color:#ffff55">if</span> <span style="color:#ffffff">(</span><span style="color:#ffffff">!</span><span style="color:#ffffff">loadedImage</span><span style="color:#ffffff">.</span><span style="color:#ffffff">load</span><span style="color:#ffffff">(</span><span style="color:#ffffff">fileName</span><span style="color:#ffffff">))</span>
<span style="color:#ffff55">return</span> <span style="color:#ffff55">false</span><span style="color:#ffffff">;</span>
<a data-cke-saved-href="https://doc.qt.io/qt-6/qsize.html" href="https://doc.qt.io/qt-6/qsize.html"><span style="color:#21be2b">QSize</span></a><span style="color:#ffffff"> newSize </span><span style="color:#ffffff">=</span><span style="color:#ffffff"> loadedImage</span><span style="color:#ffffff">.</span><span style="color:#ffffff">size</span><span style="color:#ffffff">()</span><span style="color:#ffffff">.</span><span style="color:#ffffff">expandedTo</span><span style="color:#ffffff">(</span><span style="color:#ffffff">size</span><span style="color:#ffffff">());</span><span style="color:#ffffff">
resizeImage</span><span style="color:#ffffff">(</span><span style="color:#ffffff">&</span><span style="color:#ffffff">loadedImage</span><span style="color:#ffffff">,</span><span style="color:#ffffff"> newSize</span><span style="color:#ffffff">);</span><span style="color:#ffffff">
image </span><span style="color:#ffffff">=</span><span style="color:#ffffff"> loadedImage</span><span style="color:#ffffff">;</span><span style="color:#ffffff">
modified </span><span style="color:#ffffff">=</span> <span style="color:#ffff55">false</span><span style="color:#ffffff">;</span><span style="color:#ffffff">
update</span><span style="color:#ffffff">();</span>
<span style="color:#ffff55">return</span> <span style="color:#ffff55">true</span><span style="color:#ffffff">;</span>
<span style="color:#ffffff">}</span></span></span></span>
在函数中,我们加载给定的图像。然后,我们使用私有函数将加载的大小调整为至少与两个方向上的小部件一样大,并将成员变量设置为加载的图像。最后,我们调用 () 来安排重绘。openImage()
resizeImage()
image
<span style="color:#404244"><span style="background-color:#3a4055"><span style="color:#ffffff"><span style="color:#ffff55">bool</span> <span style="color:#4f9d08">ScribbleArea</span><span style="color:#ffffff">::</span><span style="color:#ffffff">saveImage</span><span style="color:#ffffff">(</span><span style="color:#ffff55">const</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qstring.html" href="https://doc.qt.io/qt-6/qstring.html"><span style="color:#21be2b">QString</span></a> <span style="color:#ffffff">&</span><span style="color:#ffffff">fileName</span><span style="color:#ffffff">,</span> <span style="color:#ffff55">const</span> <span style="color:#ffff55">char</span> <span style="color:#ffffff">*</span><span style="color:#ffffff">fileFormat</span><span style="color:#ffffff">)</span>
<span style="color:#ffffff">{</span>
<a data-cke-saved-href="https://doc.qt.io/qt-6/qimage.html" href="https://doc.qt.io/qt-6/qimage.html"><span style="color:#21be2b">QImage</span></a><span style="color:#ffffff"> visibleImage </span><span style="color:#ffffff">=</span><span style="color:#ffffff"> image</span><span style="color:#ffffff">;</span><span style="color:#ffffff">
resizeImage</span><span style="color:#ffffff">(</span><span style="color:#ffffff">&</span><span style="color:#ffffff">visibleImage</span><span style="color:#ffffff">,</span><span style="color:#ffffff"> size</span><span style="color:#ffffff">());</span>
<span style="color:#ffff55">if</span> <span style="color:#ffffff">(</span><span style="color:#ffffff">visibleImage</span><span style="color:#ffffff">.</span><span style="color:#ffffff">save</span><span style="color:#ffffff">(</span><span style="color:#ffffff">fileName</span><span style="color:#ffffff">,</span><span style="color:#ffffff"> fileFormat</span><span style="color:#ffffff">))</span> <span style="color:#ffffff">{</span><span style="color:#ffffff">
modified </span><span style="color:#ffffff">=</span> <span style="color:#ffff55">false</span><span style="color:#ffffff">;</span>
<span style="color:#ffff55">return</span> <span style="color:#ffff55">true</span><span style="color:#ffffff">;</span>
<span style="color:#ffffff">}</span>
<span style="color:#ffff55">return</span> <span style="color:#ffff55">false</span><span style="color:#ffffff">;</span>
<span style="color:#ffffff">}</span></span></span></span>
该函数创建一个仅覆盖实际可见部分的对象,并使用 () 保存它。如果图像成功保存,我们将涂鸦区域的变量设置为 ,因为没有未保存的数据。saveImage()
image
modified
false
<span style="color:#404244"><span style="background-color:#3a4055"><span style="color:#ffffff"><span style="color:#ffff55">void</span> <span style="color:#4f9d08">ScribbleArea</span><span style="color:#ffffff">::</span><span style="color:#ffffff">setPenColor</span><span style="color:#ffffff">(</span><span style="color:#ffff55">const</span> <a data-cke-saved-href="https://doc.qt.io/qt-6/qcolor.html" href="https://doc.qt.io/qt-6/qcolor.html"><span style="color:#21be2b">QColor</span></a> <span style="color:#ffffff">&</span><span style="color:#ffffff">newColor</span><span style="color:#ffffff">)</span>
<span style="color:#ffffff">{</span><span style="color:#ffffff">
myPenColor </span><span style="color:#ffffff">=</span><span style="color:#ffffff"> newColor</span><span style="color:#ffffff">;</span>
<span style="color:#ffffff">}</span>
<span style="color:#ffff55">void</span> <span style="color:#4f9d08">ScribbleArea</span><span style="color:#ffffff">::</span><span style="color:#ffffff">setPenWidth</span><span style="color:#ffffff">(</span><span style="color:#ffff55">int</span><span style="color:#ffffff"> newWidth</span><span style="color:#ffffff">)</span>
<span style="color:#ffffff">{</span><span style="color:#ffffff">
myPenWidth </span><span style="color:#ffffff">=</span><span style="color:#ffffff"> newWidth</span><span style="color:#ffffff">;</span>
<span style="color:#ffffff">}</span></span></span></span>
和函数设置当前笔的颜色和宽度。这些值将用于将来的绘图操作。setPenColor()
setPenWidth()
<span style="color:#404244"><span style="background-color:#3a4055"><span style="color:#ffffff"><span style="color:#ffff55">void</span> <span style="color:#4f9d08">ScribbleArea</span><span style="color:#ffffff">::</span><span style="color:#ffffff">clearImage</span><span style="color:#ffffff">()</span>
<span style="color:#ffffff">{</span><span style="color:#ffffff">
image</span><span style="color:#ffffff">.</span><span style="color:#ffffff">fill</span><span style="color:#ffffff">(</span><a data-cke-saved-href="https://doc.qt.io/qt-6/qcolor.html#qRgb" href="https://doc.qt.io/qt-6/qcolor.html#qRgb"><span style="color:#ffffff">qRgb</span></a><span style="color:#ffffff">(</span><span style="color:#ff55ff">255</span><span style="color:#ffffff">,</span> <span style="color:#ff55ff">255</span><span style="color:#ffffff">,</span> <span style="color:#ff55ff">255</span><span style="color:#ffffff">));</span><span style="color:#ffffff">
modified </span><span style="color:#ffffff">=</span> <span style="color:#ffff55">true</span><span style="color:#ffffff">;</span><span style="color:#ffffff">
update</span><span style="color:#ffffff">();</span>
<sp