Qt之PaintEvent

阅读: 评论:0

Qt之PaintEvent

Qt之PaintEvent

从Qt官方给的例程可以看出,如果想将绘图加入事件循环共有两种方式:绘图事件和定时器事件两种方式,通常使用前者。

(一) painterEvent

在绘图事件中,如果想使用update()刷新页面是行不通的,除非使用新的定时器定时刷新页面。painterEvent来自QWidget的virtual protected function,其他一些控件例如QLabel、QLineEdit、QMenuBar等的painterEvent也是继承QWidget的。所以这些有继承QWidget的类中基本都存在painterEvent。

QWidget的继承类

Phonon::EffectWidget,Phonon::SeekSlider, Phonon::VideoPlayer,Phonon::VideoWidget,

 Phonon::VolumeSlider,Q3ComboBox, Q3DataBrowser, Q3DataView,Q3DateTimeEdit, 

Q3DateTimeEditBase, Q3DockArea,Q3Header, Q3MainWindow, QAbstractButton,QAbstractSlider,

 QAbstractSpinBox, QAxWidget,QCalendarWidget, QComboBox,QDesignerActionEditorInterface,

QDesignerFormWindowInterface,QDesignerObjectInspectorInterface,QDesignerPropertyEditorInterface,

QDesignerWidgetBoxInterface, QDesktopWidget,QDialog, QDialogButtonBox, QDockWidget,QFocusFrame, 

QFrame, QGLWidget, QGroupBox,QHelpSearchQueryWidget, QHelpSearchResultWidget,QLineEdit, 

QMacCocoaViewContainer,QMacNativeWidget, QMainWindow, QMdiSubWindow,QMenu, QMenuBar, 

QPrintPreviewWidget,QProgressBar, QRubberBand, QSizeGrip,QSplashScreen, QSplitterHandle, QStatusBar,

QSvgWidget, QTabBar, QTabWidget, QToolBar,QWebInspector, QWebView, QWizardPage,QWorkspace, 

QWSEmbedWidget,QX11EmbedContainer,QX11EmbedWidget.

 这就意味着这些类的子类都能通过重写painterEvent()实现绘图事件循环。

void QWidget::paintEvent ( QPaintEvent * event ) [virtual protected]

以下为Qt官方例程(Basic Drawing)的代码:

/**
*  Renderarea.h
*/
#ifndef RENDERAREA_H#define RENDERAREA_H#include <QBrush>#include <QPen>#include <QPixmap>#include <QWidget>class RenderArea : public QWidget{Q_OBJECTpublic:enum Shape { Line, Points, Polyline, Polygon, Rect, RoundedRect, Ellipse, Arc,Chord, Pie, Path, Text, Pixmap };RenderArea(QWidget *parent = 0);QSize minimumSizeHint() const;QSize sizeHint() const;public slots:void setShape(Shape shape);void setPen(const QPen &pen);void setBrush(const QBrush &brush);void setAntialiased(bool antialiased);void setTransformed(bool transformed);protected:void paintEvent(QPaintEvent *event);private:Shape shape;QPen pen;QBrush brush;bool antialiased;bool transformed;QPixmap pixmap;};#endif
/**
*    Window.h
*/ 
#ifndef WINDOW_H#define WINDOW_H#include <QWidget>class QCheckBox;class QComboBox;class QLabel;class QSpinBox;class RenderArea;class Window : public QWidget{Q_OBJECTpublic:Window();private slots:void shapeChanged();void penChanged();void brushChanged();private:RenderArea *renderArea;QLabel *shapeLabel;QLabel *penWidthLabel;
......	};#endif

然后在window.cpp文件中将renderArea对象按照qwidget处理即可;

这样处理完后即可进入事件循环了。

下来就是重头戏:在painterEvent()里画图!

在画图之前需要前置知识点:

(1)  Qt坐标系统

.html

但是上面两篇关于视口和窗口的介绍没怎么看明白,得多琢磨下。

/**
* Painter.cpp
*/
QPainter Painter(this);Painter.setRenderHint(QPainter::Antialiasing, true);///抗锯齿QPainterPath Path,Path1;    ///路径QSize ViewSize(100,100);const QRectF Xrectf[5] ={QRectF(1,19,1.5,18),QRectF(5,19.1,6,18),QRectF(9.5,19.1,10,18),QRectF(13.5,19.1,14,18),QRectF(17.5,19.1,18,18)};const QRectF Yrectf[5] ={          ///字的位置QRectF(0.5,19,1.5,19.5),QRectF(0.5,15,1.5,15.5),QRectF(0.5,11,1.5,11.5),QRectF(0.5,7,1.5,7.5),QRectF(0.5,3,1.5,3.5)};QPolygonF polygon,polygon1;const QPoint Xpoints[5]= {QPoint(2,20),QPoint(6,20),QPoint(10,20),QPoint(14,20),QPoint(18,20)};const QPoint Ypoints[5]= {QPoint(2,20),QPoint(2,16),QPoint(2,12),QPoint(2,8),QPoint(2,4)};QFont font("Arial",1,QFont::Black);Painter.scale(15,15);                     ///x,y放大15倍//ate(-45);                     ///旋转角度Painter.setViewport(0,0,ViewSize.width(),ViewSize.height());Painter.setWindow(0,0,ViewSize.width(),/*-1**/ViewSize.height());QPen Pen(Qt::red, 0, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin); ///红色,实线Painter.setPen(Pen);Painter.setBrush(Qt::NoBrush);         ///不用刷子Painter.drawLine(1,20,22,20);			///连(1,20)->(22,20)Painter.drawLine(2,2,2,22);veTo(1,3), Path.lineTo(2,2), Path.lineTo(3,3);veTo(21,19),Path1.lineTo(22,20),Path1.lineTo(21,21);///路径Painter.drawPath(Path),Painter.drawPath(Path1);QPen Pen1(Qt::blue, 0.2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);Painter.setFont(font);               ///设置字体 arial 字宽1, 黑色Painter.setPen(Pen1);for(int i = 0; i < 5;i++){Painter.drawPoint(Xpoints[i]);Painter.drawPoint(Ypoints[i]);Painter.drawText(Xrectf[i],QString::number(i*5));Painter.drawText(Yrectf[i],QString::number(i*5));}QPen Pen2(Qt::yellow);QPolygon polygon2;int x = generateRandomNumber(19);int y = generateRandomNumber(20);polygon2 << TransformToNewAxis(0,0) << TransformToNewAxis(0,y) << TransformToNewAxis(x,y) << TransformToNewAxis(x+1,0);   ///多边形Painter.setPen(Pen2);const QColor colors[5] = {QColor(16,78,139),QColor(255,62,150),QColor(58,95,205),QColor(0,238,0),QColor(153,50,204)};int col = generateRandomNumber(5);QBrush shape(colors[col],Qt::SolidPattern);Painter.setBrush(shape);         ///给多边形填充颜色Painter.drawPolygon(polygon2);this->update();

(二)TimerEvent

在timerEvent就比较容易控制绘图的刷新了,因为是定时器事件,可以控制时间。在官方例程中也提供了这种方法:

/**
*    PathDeform.h
*/
#ifndef PATHDEFORM_H#define PATHDEFORM_H#include "arthurwidgets.h"#include <QPainterPath>#include <QBasicTimer>#include <QDateTime>class PathDeformRenderer : public ArthurFrame{Q_OBJECTQ_PROPERTY(bool animated READ animated WRITE setAnimated)Q_PROPERTY(int radius READ radius WRITE setRadius)Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize)Q_PROPERTY(int intensity READ intensity WRITE setIntensity)Q_PROPERTY(QString text READ text WRITE setText)public:PathDeformRenderer(QWidget *widget, bool smallScreen = false);void paint(QPainter *painter);void mousePressEvent(QMouseEvent *e);void mouseReleaseEvent(QMouseEvent *e);void mouseMoveEvent(QMouseEvent *e);void timerEvent(QTimerEvent *e);QSize sizeHint() const { return QSize(600, 500); }bool animated() const { return m_animated; }int radius() const { return int(m_radius); }int fontSize() const { return m_fontSize; }int intensity() const { return int(m_intensity); }QString text() const { return m_text; }public slots:void setRadius(int radius);void setFontSize(int fontSize) { m_fontSize = fontSize; setText(m_text); }void setText(const QString &text);void setIntensity(int intensity);void setAnimated(bool animated);signals:void clicked();private:void generateLensPixmap();QPainterPath lensDeform(const QPainterPath &source, const QPointF &offset);QBasicTimer m_repaintTimer;QTime m_repaintTracker;QVector<QPainterPath> m_paths;.......};////**
*    PathDeform.cpp
*/void PathDeformRenderer::timerEvent(QTimerEvent *e){if (e->timerId() == m_repaintTimer.timerId()) { //判断定时器id是否绘图定时器的IDif (QLineF(QPointF(0,0), m_direction).length() > 1)m_direction *= 0.995;qreal time = start();QRect rectBefore = circle_bounds(m_pos, m_radius, m_fontSize);qreal dx = m_direction.x();qreal dy = m_direction.y();if (time > 0) {dx = dx * time * .1;dy = dy * time * .1;}m_pos += QPointF(dx, dy);if (m_pos.x() - m_radius < 0) {m_direction.setX(-m_direction.x());m_pos.setX(m_radius);} else if (m_pos.x() + m_radius > width()) {m_direction.setX(-m_direction.x());m_pos.setX(width() - m_radius);}if (m_pos.y() - m_radius < 0) {m_direction.setY(-m_direction.y());m_pos.setY(m_radius);} else if (m_pos.y() + m_radius > height()) {m_direction.setY(-m_direction.y());m_pos.setY(height() - m_radius);}#ifdef QT_OPENGL_SUPPORTif (usesOpenGL()) {update();} else#endif{QRect rectAfter = circle_bounds(m_pos, m_radius, m_fontSize);update(rectAfter | rectBefore);QApplication::syncX();}}}void PathDeformRenderer::mouseReleaseEvent(QMouseEvent *e){if (e->buttons() == Qt::NoButton && m_animated) {m_repaintTimer.start(10, this);m_repaintTracker.start();}if (!m_mouseDrag && m_smallScreen)emit clicked();}

然后其他地方启动绘图的定时器即可。

本文发布于:2024-02-02 05:14:37,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170682207841587.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:Qt   PaintEvent
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23