范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Qt绘制系统

  Qt绘制系统简介##
  Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制。整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类。 QPainter用来执行绘制的操作; QPaintDevice是一个二维空间的抽象,这个二维空间允许QPainter在其上面进行绘制,也就是QPainter工作的空间; QPaintEngine提供了画笔(QPainter)在不同的设备上进行绘制的统一的接口。QPaintEngine类应用于QPainter和QPaintDevice之间,通常对开发人员是透明的。除非你需要自定义一个设备,否则你是不需要关心QPaintEngine这个类的。
  我们可以把QPainter理解成画笔;把QPaintDevice理解成使用画笔的地方,比如纸张、屏幕等;而对于纸张、屏幕而言,肯定要使用不同的画笔绘制,为了统一使用一种画笔,我们设计了QPaintEngine类,这个类让不同的纸张、屏幕都能使用一种画笔。 程序###
  main.cpp #include  #include "paint.h"  int main(int argc, char **argv) {     QApplication a(argc, argv);     PaintedWidget mywindow;     mywindow.show();     return a.exec(); }
  paint.h #include  #include   class PaintedWidget : public QWidget {     Q_OBJECT public:     PaintedWidget(QWidget *parent = 0); protected:     void paintEvent(QPaintEvent *); };
  paint.cpp #include "paint.h" PaintedWidget::PaintedWidget(QWidget *parent) :     QWidget(parent) {     resize(400, 400);     setWindowTitle(tr("Paint Demo")); }  void PaintedWidget::paintEvent(QPaintEvent *) {     QPainter painter(this);     QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin);     painter.setPen(pen);     painter.drawLine(80, 100, 300, 300);     painter.setPen(Qt::red);     painter.drawRect(10, 10, 100, 300);     painter.setPen(QPen(Qt::green, 5));     painter.setBrush(Qt::blue);     painter.drawEllipse(50, 150, 200, 100); }
  在构造函数中,我们仅仅设置了窗口的大小和标题。
  paintEvent()函数则是绘制的代码。首先,我们在栈上创建了一个QPainter对象,也就是说,每次运行paintEvent()函数的时候,都会重建这个QPainter对象。QPainter接收一个QPaintDevice指针作为参数。QPaintDevice有很多子类,比如QImage,以及QWidget。QPaintDevice可以理解成要在哪里去绘制,而现在我们希望画在这个组件,因此传入的是 this 指针。
  注意,这一点可能会引发某些细节问题:由于我们每次重建QPainter,因此第一次运行时所设置的画笔颜色、状态等,第二次再进入这个函数时就会全部丢失。有时候我们希望保存画笔状态,就必须自己保存数据,否则的话则需要将QPainter作为类的成员变量。paintEvent() 作为重绘函数,会在需要重绘时由 Qt 自动调用。"需要重绘"可能发生在很多地方,比如组件刚刚创建出来的时候就需要重绘;组件最大化、最小化的时候也需要重新绘制;组件由遮挡变成完全显示的时候也需要等等。 程序运行结果###
  画刷和画笔##
  Qt 绘图系统定义了两个绘制时使用的关键属性:画刷和画笔。前者使用QBrush描述,大多用于填充;后者使用QPen描述,大多用于绘制轮廓线。 画刷###画刷的style()定义了填充的样式,使用Qt::BrushStyle枚举,默认值是Qt::NoBrush,也就是不进行任何填充。我们可以从下面的图示中看到各种填充样式的区别: 画刷的color()定义了填充模式的颜色。这个颜色可以是 Qt 预定义的颜色常量,也就是Qt::GlobalColor,也可以是任意QColor对象。 画刷的gradient()定义了渐变填充。这个属性只有在样式是Qt::LinearGradientPattern、Qt::RadialGradientPattern或者Qt::ConicalGradientPattern之一时才有效。渐变可以由QGradient对象表示。Qt 提供了三种渐变:QLinearGradient、QConicalGradient和QRadialGradient,它们都是QGradient的子类。我们可以使用如下代码片段来定义一个渐变的画刷:         QPainter painter(this);         QLinearGradient linearGradient(200, 50, 300, 50);         linearGradient.setColorAt(0, Qt::red);         linearGradient.setColorAt(1, Qt::green);         painter.setBrush(linearGradient);         painter.drawEllipse(QPointF(250, 50), 50, 50);          QRadialGradient radialGradient(QPointF(50, 50), 50, QPointF(50, 50));         radialGradient.setColorAt(0, QColor(255, 255, 100, 150));         radialGradient.setColorAt(1, QColor(0, 0, 0, 50));         painter.setBrush(radialGradient);         painter.drawEllipse(QPointF(50, 50), 50, 50);          QConicalGradient conicalGradient(QPointF(150, 50), 60);         conicalGradient.setColorAt(0.2, Qt::white);         conicalGradient.setColorAt(0.9, Qt::black);         painter.setBrush(conicalGradient);         painter.drawEllipse(QPointF(150, 50), 50, 50);
  运行结果如下:
  画刷样式是 Qt::TexturePattern时,texture()定义了用于填充的纹理。注意,即使你没有设置样式为Qt::TexturePattern,当你调用setTexture()函数时,QBrush会自动将style()设置为Qt::TexturePattern。     QPainter painter(this);     QBrush brush;     brush.setTexture(QPixmap("image.jpg"));     painter.setBrush(brush);     painter.drawEllipse(50, 100, 300, 200);
  运行结果:
  画笔###
  QPen定义了用于QPainter应该怎样画线或者轮廓线。
  画笔具有样式、宽度、画刷、笔帽样式和连接样式等属性。 1.画笔的样式style()定义了线的样式。画刷brush()用于填充画笔所绘制的线条。 2.笔帽样式capStyle()定义了使用QPainter绘制的线的末端; 3.连接样式joinStyle()则定义了两条线如何连接起来。 4.画笔宽度width()或widthF()定义了画笔的宽。注意,不存在宽度为 0 的线。
  注:假设你设置 width 为 0,QPainter依然会绘制出一条线,而这个线的宽度为 1 像素。也就是说,画笔宽度通常至少是 1 像素。
  这么多参数既可以在构造时指定,也可以使用 set 函数指定,完全取决于你的习惯,例如: QPainter painter(this); QPen pen(Qt::green, 3, Qt::DashDotLine, Qt::RoundCap, Qt::RoundJoin); painter.setPen(pen);
  等价于 QPainter painter(this); QPen pen;  // creates a default pen  pen.setStyle(Qt::DashDotLine); pen.setWidth(3); pen.setBrush(Qt::green); pen.setCapStyle(Qt::RoundCap); pen.setJoinStyle(Qt::RoundJoin);  painter.setPen(pen);
  使用构造函数的优点是代码较短,但是参数含义不明确;使用 set 函数则正好反过来。
  默认的画笔属性是纯黑色,0 像素,方形笔帽(Qt::SquareCap),斜面型连接(Qt::BevelJoin)。 1.下面是画笔样式的示例:####
  你也可以使用setDashPattern()函数自定义样式,例如如下代码片段:  QPen pen;  QVector dashes;  qreal space = 4;  dashes << 1 << space << 3 << space << 9 << space         << 27 << space << 9 << space;  pen.setDashPattern(dashes); 2.笔帽定义了画笔末端的样式,例如:####
  他们之间的区别是,Qt::SquareCap是一种包含了最后一个点的方形端点,使用半个线宽覆盖;Qt::FlatCap不包含最后一个点;Qt::RoundCap是包含最后一个点的圆形端点。具体可以参考下面的示例(出自《C++ GUI Programming with Qt 4, 2nd Edition》):
  3.连接样式定义了两条线连接时的样式,例如:####
  同样,可以参考下面图示来理解这几种连接样式的细节(出自《C++ GUI Programming with Qt 4, 2nd Edition》):
  反走样##
  我们在光栅图形显示器上绘制非水平、非垂直的直线或多边形边界时,或多或少会呈现锯齿状外观。这是因为直线和多边形的边界是连续的,而光栅则是由离散的点组成。在光栅显示设备上表现直线、多边形等,必须在离散位置采样。由于采样不充分重建后造成的信息失真,就叫走样;用于减少或消除这种效果的技术,就称为反走样。
  反走样是图形学中的重要概念,用以防止通常所说的"锯齿"现象的出现。很多系统的绘图 API 里面都内置了有关反走样的算法,不过由于性能问题,默认一般是关闭的,Qt 也不例外。下面我们来看看代码: void paintEvent(QPaintEvent *) {         QPainter painter(this);         painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));         painter.setBrush(Qt::yellow);         painter.drawEllipse(100, 50, 200, 150);          painter.setRenderHint(QPainter::Antialiasing, true);         painter.setPen(QPen(Qt::black, 5, Qt::DashDotLine, Qt::RoundCap));         painter.setBrush(Qt::yellow);         painter.drawEllipse(100, 220, 200, 150); }
  显然,我们通过这条语句,将Antialiasing属性(也就是反走样)设置为 true。经过这句设置,我们就打开了QPainter的反走样功能。还记得我们曾经说过,QPainter是一个状态机,因此,只要这里我们打开了它,之后所有的代码都会是反走样绘制的了。
  点击领取Qt学习资料+视频教程~「链接」
  坐标变换###
  前面说过,QPainter是一个状态机。那么,有时我想保存下当前的状态:当我临时绘制某些图像时,就可能想这么做。当然,我们有最原始的办法:将可能改变的状态,比如画笔颜色、粗细等,在临时绘制结束之后再全部恢复。对此,QPainter提供了内置的函数:save()和restore()。save()就是保存下当前状态;restore()则恢复上一次保存的结果。这两个函数必须成对出现:QPainter使用栈来保存数据,每一次save(),将当前状态压入栈顶,restore()则弹出栈顶进行恢复。
  在了解了这两个函数之后,我们就可以进行示例代码了: void PaintDemo::paintEvent(QPaintEvent *) {         QPainter painter(this);         painter.fillRect(10, 10, 50, 100, Qt::red);         painter.save();         painter.translate(100, 0); // 向右平移 100px         painter.fillRect(10, 10, 50, 100, Qt::yellow);         painter.restore();         painter.save();         painter.translate(300, 0); // 向右平移 300px         painter.rotate(30); // 顺时针旋转 30 度         painter.fillRect(10, 10, 50, 100, Qt::green);         painter.restore();         painter.save();         painter.translate(0, 100); // 向下平移 100px         painter.scale(2, 2); // 横坐标单位放大 2 倍,纵坐标放大 2 倍         painter.fillRect(10, 10, 50, 100, Qt::blue);         painter.restore();         painter.save();         painter.translate(200, 100); // 向右平移 200px 向下平移 100px         painter.shear(0, 1); // 横向不变,纵向扭曲 1 倍         painter.fillRect(10, 10, 50, 100, Qt::cyan);         painter.restore(); }
  Qt 提供了四种坐标变换:平移 translate,旋转 rotate,缩放 scale 和扭曲 shear。在这段代码中,我们首先在 (10, 10) 点绘制一个红色的 50×100 矩形。保存当前状态,将坐标系平移到 (100, 0),绘制一个黄色的矩形。注意,translate()操作平移的是坐标系,不是矩形。因此,我们还是在 (10, 10) 点绘制一个 50×100 矩形,现在,它跑到了右侧的位置。然后恢复先前状态,也就是把坐标系重新设为默认坐标系(相当于进行translate(-100, 0)),再进行下面的操作。之后也是类似的。由于我们只是保存了默认坐标系的状态,因此我们之后的translate()横坐标值必须增加,否则就会覆盖掉前面的图形。所有这些操作都是针对坐标系的,因此在绘制时,我们提供的矩形的坐标参数都是不变的。
  运行结果如下:
  窗口坐标###void PaintDemo::paintEvent(QPaintEvent *) {     QPainter painter(this);     painter.setWindow(0, 0, 200, 200);     painter.fillRect(0, 0, 200, 200, Qt::red); }
  运行结果:
  原本窗口大小为400 400,但这里利用setWindow重新分配了窗口坐标为200 200,即便拖动窗口大小红色矩形也会覆盖整个窗口,由于setWindow将窗口的左上角固定位(0,0)窗口的右下角固定为(200,200)。此时再画矩形就是在这个窗口坐标下画。 视口坐标###    QPainter painter(this);     painter.setWindow(0, 0, 200, 200);     painter.setViewport(100, 100, 100, 100);     painter.fillRect(0, 0, 200, 200, Qt::red);
  利用setVieweport将窗口映射到视口。

国际乒联最新世界排名樊振东继续第一,马龙第二中新网2月28日电28日,国际乒联更新2023年第9周世界排名。男单排名中,樊振东马龙王楚钦排名前三。女单方面孙颖莎陈梦王曼昱位居前三。男单排名。国际乒联网站截图男单方面,樊振东继陕西省首届三人篮球联赛榆林赛区开赛2月25日,陕西省首届延长石油杯三人篮球联赛榆林赛区暨榆阳赛区启动仪式在榆林市体育馆举行。本次比赛由省体育局主办,设置省市县镇四级竞赛层级和乡镇社区行业青少年俱乐部五大板块,其中,甘肃临夏机场何时开建?官方回复来了近日,有甘肃临夏网友在人民网领导留言板留言,反映临夏民用机场为何迟迟不见落地的问题。对此,临夏州发展和改革委员会回复,临夏机场项目立项请示已由省政府上报国务院中央军委。目前,国务院甘孜州局长强硬手腕应对差评旅店甘孜州网红局长刘洪一身武侠装扮迷倒万千观众,他本身就是318上一道独特的风景线。在工作中也是霹雳手段,为维护甘孜州良好的旅游环境重拳出击。外地小伙退房,旅馆老板心生不满,产生矛盾,看振兴陕西行丨今日南泥湾,红色旅游让年轻人回流新京报讯(记者曹晶瑞王颖)错落有致的民居,纵横交错的柏油小路,精品酒店民宿幼儿园农庄400余座现代农业温室大棚勾勒出红色旅游村陕西省延安市南泥湾镇马坊村的振兴新貌。南泥湾党徽广场。中华民国临时政府中华民国临时政府是中华民国于1912年1月1日成立后不久由孙中山在南京成立的一个临时管治机构,也是中华民国建国以来第一个中央政府机构,又称南京临时政府,简称临政。孙中山宣誓就任中华陕西学者耗时7年,取得原行星盘演变新进展,2项成果获国际认可!近期,西安电子科技大学物理学院王欣明老师在原行星盘演变研究中取得新进展,并作为独立作者在国际天文学及天体物理学领域顶级期刊TheAstrophysicalJournal(天体物理学专访横琴粤澳深度合作区金融发展局局长池腾辉横琴金融政策体系初步成型跨境业务创新与风险防范处置双轮驱动随着系列金融政策出台,琴澳金融业正迈向纵深发展。2月23日,关于金融支持横琴粤澳深度合作区建设的意见(简称意见)发布,共提出30条金融改革创新举措,为粤港澳大湾区建设探索金融支持新网红局长力挽狂澜,差评秒变旅游攻略,这样的好干部多来点高大帅气的网红局长刘洪又火了,这两天,他掷地有声的金句传遍全网如果谁砸了我们甘孜旅游的锅,我一定砸了你的饭碗。刘洪变装推广甘孜旅游刘洪50岁,是四川省甘孜州文旅局局长,毕业于中央民甘肃五环公司2023职业素质提升营首课新闻写作篇内容开讲为进一步加强公司新闻宣传工作,提升全员新闻写作水平,营造公司施工生产企业发展的良好舆论环境,近日,五环公司2023职业素质提升营首课新闻写作篇内容开讲。公司机关各项目和子公司共16乡村振兴看陕西丨延安赵家岸村多业态谋发展小村庄释放大能量闲置窑洞变特色民宿,文化长廊让你沉浸式体验陕北非遗,周边还有大棚可采摘,山庄可垂钓近些年来,位于陕西延安河庄坪镇的赵家岸村,遵循政府企业学校共建共享共用的模式,因地制宜构建起多业态