第八章 二维图形

来源:互联网 发布:php案例教程 多图 编辑:程序博客网 时间:2024/05/17 01:07

    前面大多学的是控件用户界面的安排学习,现在是Qt一个极其重要的方面,就是在绘制二维图形方面的强大功能,在使用得当情况下绝大部分你需要的界面和图形都能非常好看,也有很多自带的的和第三方图形库能够使用,会比手动绘制方便的多,就看你用的溜不溜了。

    Qt的二维图形引擎是基于QPainter类的。QPainter既可以绘制几何形状也可以绘制像素文字等元素。还支持一些高级特性,反走样、像素混合、渐变填充、矢量路径之类的,还有线性变换、平移旋转什么的,可谓老牛逼了。

    重新实现QWidget::painterEvent()可以用于定制窗口部件,并且相当随便的控制外观。Qt也有QGraphicsView、QGraphicsScene和QGraphicsItem类引用全新的“图形视图”体系。可以供交互、绘制、操作。QpenGL是一个绘制三维图形的标准库,也很厉害,以后详述。

一、使用QPainter绘图

    要想在绘图设备上(一般指的是窗口部件)上绘图,只需要创建一个QPainter,再将指针传到该设备中。

例如:

void MyWidget::paintEvent(QPaintEvent *event){    QPainter painter(this);}

QPainter的drawXXX()函数可以绘制各种形状,当然前提是设置好工具的属性。

查看Qt助手对这些绘图的理解帮助会非常大。


QPainter可以这样用:

void Widget:: draw(){    QPainter painter( this );    painter. setPen( QPen ( Qt :: black, 10 , Qt :: DashDotLine, Qt :: RoundCap));    painter. setBrush( QBrush ( Qt :: green, Qt :: SolidPattern));    painter. drawEllipse( 10 , 10 , 400 , 240 );    painter. drawRect( QRect ( 10 , 300 , 400 , 140 ));}
可以这样用嘞:

void Widget:: drawBezier(){    QPainter painter( this );painter. setRenderHint( QPainter :: Antialiasing, true );     QPainterPath path;    path. moveTo( 10 , 320 );path. cubicTo( 200 , 80 , 400 , 80 , 480 , 320 );     painter. setPen( QPen ( Qt :: black, 2 ));painter. drawPath( path);     painter. setPen( QPen ( Qt :: red, 4 ));    painter. drawPoint( 10 , 320 );     painter. drawPoint( 200 , 80 );    painter. drawPoint( 400 , 80 );    painter. drawPoint( 480 , 320 );}

下面做一个QPainter的实例,一个改变绘图的控制器,当然是不完善的。
#include "painterarea.h"

#ifndef PAINTAREA_H#define PAINTAREA_H#include <QWidget>#include <QPen>#include <QPaintEvent>class PaintArea : public QWidget{Q_OBJECTpublic:enum Shape {Line, Rectangle, RoundRect, Ellipse, Polygon, Polyline, Points, Arc, Path, Text,Pixmap};PaintArea(QWidget * parent = 0);void setShape(Shape);       //设置形状void setPen(QPen);          //设置画笔void setBrush(QBrush);      //设置画刷void setFillRule(Qt::FillRule);//设置填充模式void paintEvent(QPaintEvent *);//重画事件private:Shape shape;QPen pen;QBrush brush;Qt::FillRule fillRule;};#endif // PAINTAREA_H

painterarea.cpp

#include "painterarea.h"#include <QPainter>PaintArea::PaintArea(QWidget *parent):QWidget(parent){setPalette(QPalette(Qt::white)); //设置背景颜色setAutoFillBackground(true);//设置自动填充背景色setMinimumSize(400, 400);//设置窗口最下大小}void PaintArea::setShape(Shape s)   //update()更新窗口部件{shape = s;update();}void PaintArea::setPen(QPen p){pen = p;update();}void PaintArea::setBrush(QBrush b){brush = b;update();}void PaintArea::setFillRule(Qt::FillRule rule){fillRule = rule;update();}//重画事件void PaintArea::paintEvent(QPaintEvent *){QPainter p(this);p.setPen(pen);p.setBrush(brush);QRect rect(100, 100, 250, 200);//构造一个矩形static const QPoint points[4] = {QPoint(100,100),QPoint(200,150),QPoint(300,250),QPoint(150,300)};//确定Points的四个点的坐标int startAngle = 60 * 16;int spanAngle = 180 * 16;  //为绘制曲线设置参数变量QPainterPath path;     //QPainterPath为Qpainter类提供了一个存储容器,里面包含了画的内容和画的顺序,path.moveTo(50, 150);    //当前位置移动到坐标50,150path.lineTo(350, 150);   //当前位置开始画直线,终点位置坐标350,150path.lineTo(100, 325);path.lineTo(200, 50);path.lineTo(300, 325);path.lineTo(50, 150);path.setFillRule(fillRule);  //设置填充模式switch (shape){case Line:       //直线p.drawLine(rect.topLeft(), rect.bottomRight());  //绘制直线。起点为矩形左上点,终点为矩形右下点break;case Rectangle: //长方形p.drawRect(rect);break;case RoundRect:  //圆角方形p.drawRoundRect(rect);break;case Ellipse:   //椭圆形p.drawEllipse(rect);break;case Polygon:   //多边形p.drawPolygon(points, 4);  //绘制4个顶点多边形break;case Polyline:  //多边线p.drawPolyline(points, 4);break;case Points:    //点p.drawPoints(points, 4);break;case Arc:   //弧p.drawArc(rect, startAngle, spanAngle);  //后面两个参数分别为 起始角与跨度角break;case Path:  //绘制之前已经画好的路径p.drawPath(path);break;case Text:  //文字p.drawText(rect, Qt::AlignCenter, tr("Hello Qt!"));break;case Pixmap:    //图片p.drawPixmap(150, 150, QPixmap("1.png"));//绘制一个图像break;default:break;}}//前面的椭圆形、直线、长方形、圆角矩形,弧 都是利用矩形为骨架构成的,具体如何构成参照介绍中的绘制函数中的图。

void PaintArea::paintEvent(QPaintEvent *)
函数内的Point是确定的四个点当然可以根据你的需要设置成鼠标按压事件给出的坐标来

#include"mainwindow.h"

#pragma once#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QWidget>#include <painterarea.h>#include <QLabel>#include <QComboBox>#include <QSpinBox>#include <QPushButton>#include <QGridLayout>class MainWindow : public QWidget{Q_OBJECTpublic:MainWindow(QWidget *parent = 0);~MainWindow();private:PaintArea *paintArea;QLabel *shapelabel;//形状QComboBox *shapeComboBox;QLabel *penWidthLable;//画笔宽度QSpinBox *penWidthSpinBox;QLabel *penColorLabel;//画笔颜色QFrame *penColorFrame;QPushButton *penColorbtn;//画笔颜色按钮QLabel *penStyleLabel;QComboBox *penStyleComboBox;//画笔风格QLabel *penCapLabel;QComboBox *penCapComboBox;QLabel *penJoinLabel;QComboBox *penJoinComboBox;QLabel *fillLabel;QComboBox *fillComboBox;QLabel *brushStyleLabel;QComboBox *brushStyleComboBox;QLabel *brushColorlabel;QFrame *brushColorFrame;QPushButton *brushColorbtn;QGridLayout *settingLayout;protected slots:void ShowShape(int);void ShowPenWidth(int);void ShowPenColor();void ShowPenStyle(int);void ShowPenCap(int);void ShowPenJoin(int);void ShowFill();void ShowBrushColor();void ShowBrush(int);};#endif // MAINWINDOW_H


mainwindow.cpp
#include"mainwindow.h"#include "painterarea.h"#include<QColorDialog>MainWindow::MainWindow(QWidget *parent): QWidget(parent){paintArea = new PaintArea;shapelabel = new QLabel(QStringLiteral("形状:"));  //形状选择下拉列表框shapeComboBox = new QComboBox;shapeComboBox->addItem(tr("Line"), PaintArea::Line);shapeComboBox->addItem(tr("RoundRect"), PaintArea::RoundRect);shapeComboBox->addItem(tr("Ellipse"), PaintArea::Ellipse);shapeComboBox->addItem(tr("Polygon"), PaintArea::Polygon);shapeComboBox->addItem(tr("Polyline"), PaintArea::Polyline);shapeComboBox->addItem(tr("Points"), PaintArea::Points);shapeComboBox->addItem(tr("Arc"), PaintArea::Arc);shapeComboBox->addItem(tr("Rectangle"), PaintArea::Rectangle);shapeComboBox->addItem(tr("Path"), PaintArea::Path);shapeComboBox->addItem(tr("Text"), PaintArea::Text);shapeComboBox->addItem(tr("Pixmap"), PaintArea::Pixmap);connect(shapeComboBox, SIGNAL(activated(int)), this, SLOT(ShowShape(int)));penColorLabel = new QLabel(QStringLiteral("画笔颜色:")); //画笔颜色选择控件penColorFrame = new QFrame;penColorFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken);//Panel - QFrame画一个平板使内容看起来凸起或者凹陷, //QFrame::Sunken - 框架和内容看起来凹陷 penColorFrame->setAutoFillBackground(true);penColorFrame->setPalette(QPalette(Qt::blue));//设置默认颜色为蓝色penColorbtn = new QPushButton;connect(penColorbtn, SIGNAL(clicked()), this, SLOT(ShowPenColor()));penWidthLable = new QLabel(QStringLiteral("画笔宽度:"));//画笔宽度选择控件penWidthSpinBox = new QSpinBox;penWidthSpinBox->setRange(0, 20);//设置字宽滑块的取值范围connect(penWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ShowPenWidth(int)));penStyleLabel = new QLabel; //画笔风格选择下拉列表框penStyleComboBox = new QComboBox;penStyleComboBox->addItem(tr("SolidLine"), 1);penStyleComboBox->addItem(tr("DashLine"), 2);penStyleComboBox->addItem(tr("DotLine"), 3);penStyleComboBox->addItem(tr("DashDotLine"), 4);penStyleComboBox->addItem(tr("DashDotDotLine"), 5);penStyleComboBox->addItem(tr("CustomDashLine"), 6);//这段如果报错,可以把addItem后面的参数置换为int类的数字connect(penStyleComboBox, SIGNAL(activated(int)), this, SLOT(ShowPenStyle(int)));penCapLabel = new QLabel;  //画顶端风格选择下拉列表框penCapComboBox = new QComboBox;penCapComboBox->addItem(tr("SquareCap"), Qt::SquareCap);penCapComboBox->addItem(tr("FlatCap"), Qt::FlatCap);penCapComboBox->addItem(tr("RoundCap"), Qt::RoundCap);connect(penCapComboBox, SIGNAL(activated(int)), this, SLOT(ShowPenCap(int)));penJoinLabel = new QLabel;//画笔连接点风格选择下拉列表框penJoinComboBox = new QComboBox;penJoinComboBox->addItem(tr("BevelJoin"), Qt::BevelJoin);penJoinComboBox->addItem(tr("MiterJoin"), Qt::MiterJoin);penJoinComboBox->addItem(tr("RoundJoin"), Qt::RoundJoin);fillLabel = new QLabel;//填充模式选择下拉列表框fillComboBox = new QComboBox;fillComboBox->addItem(tr("Odd Even"), Qt::OddEvenFill);fillComboBox->addItem(tr("Winding"), Qt::WindingFill);connect(fillComboBox, SIGNAL(activated(int)), this, SLOT(ShowFill()));brushColorlabel = new QLabel;//画刷风格选择下拉列表框brushColorFrame = new QFrame;brushColorbtn = new QPushButton;brushColorFrame->setFrameStyle(QFrame::Panel | QFrame::Sunken);brushColorFrame->setAutoFillBackground(true);brushColorFrame->setPalette(QPalette(Qt::green));connect(brushColorbtn, SIGNAL(clicked()), this, SLOT(ShowBrushColor()));brushStyleLabel = new QLabel; //画刷风格选择下拉列表框brushStyleComboBox = new QComboBox;brushStyleComboBox->addItem(tr("SolidPattern"), 1);brushStyleComboBox->addItem(tr("Dense1Pattern"), 2);brushStyleComboBox->addItem(tr("Dense2Pattern"), 3);brushStyleComboBox->addItem(tr("Dense3Pattern"), 4);brushStyleComboBox->addItem(tr("Dense4Pattern"), 5);brushStyleComboBox->addItem(tr("Dense5Pattern"), 6);brushStyleComboBox->addItem(tr("Dense6Pattern"), 7);brushStyleComboBox->addItem(tr("Dense7Pattern"), 8);brushStyleComboBox->addItem(tr("HorPattern"), 9);brushStyleComboBox->addItem(tr("VerPattern"), 10);brushStyleComboBox->addItem(tr("CrossPattern"), 11);brushStyleComboBox->addItem(tr("BDiagPattern"), 12);brushStyleComboBox->addItem(tr("FDiagPattern"), 13);brushStyleComboBox->addItem(tr("DiagCrossPattern"), 14);brushStyleComboBox->addItem(tr("LinearGradientPattern"), 15);brushStyleComboBox->addItem(tr("ConicalGradientPattern"), 16);brushStyleComboBox->addItem(tr("RadialGradientPattern"), 17);brushStyleComboBox->addItem(tr("TexturePattern"), 24);connect(brushStyleComboBox, SIGNAL(activated(int)), this, SLOT(ShowBrush(int)));settingLayout = new QGridLayout;//画板布局settingLayout->addWidget(shapelabel, 0, 0);settingLayout->addWidget(shapeComboBox, 0, 1);settingLayout->addWidget(penColorLabel, 0, 2);settingLayout->addWidget(penColorFrame, 0, 3);settingLayout->addWidget(penColorbtn, 0, 4);settingLayout->addWidget(penWidthLable, 1, 0);settingLayout->addWidget(penWidthSpinBox, 1, 1);settingLayout->addWidget(penStyleLabel, 1, 2);settingLayout->addWidget(penStyleComboBox, 1, 3);settingLayout->addWidget(penCapLabel, 2, 0);settingLayout->addWidget(penCapComboBox, 2, 1);settingLayout->addWidget(penJoinLabel, 2, 2);settingLayout->addWidget(penJoinComboBox, 2, 3);settingLayout->addWidget(fillLabel, 3, 0);settingLayout->addWidget(fillComboBox, 3, 1);settingLayout->addWidget(brushColorlabel, 3, 2);settingLayout->addWidget(brushColorFrame, 3, 3);settingLayout->addWidget(brushColorbtn, 3, 4);settingLayout->addWidget(brushStyleLabel, 4, 0);settingLayout->addWidget(brushStyleComboBox, 4, 1);QVBoxLayout *mainLayout = new QVBoxLayout(this);mainLayout->addLayout(settingLayout);mainLayout->addWidget(paintArea);ShowShape(shapeComboBox->currentIndex());}//以下就是各种槽函数了void MainWindow::ShowShape(int value){PaintArea::Shape shape = PaintArea::Shape(shapeComboBox->itemData(value, Qt::UserRole).toInt());paintArea->setShape(shape);}void MainWindow::ShowPenWidth(int value)//画笔宽度{QColor color = penColorFrame->palette().color(QPalette::Window);Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(), Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(), Qt::UserRole).toInt());Qt::PenJoinStyle join = Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(), Qt::UserRole).toInt());paintArea->setPen(QPen(color, value, style, cap, join));}void MainWindow::ShowPenColor()//画笔颜色{QColor color = QColorDialog::getColor(Qt::blue);penColorFrame->setPalette(QPalette(color));int value = penWidthSpinBox->value();Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(), Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(), Qt::UserRole).toInt());Qt::PenJoinStyle join = Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(), Qt::UserRole).toInt());paintArea->setPen(QPen(color, value, style, cap, join));}void MainWindow::ShowPenStyle(int styleValue)//画笔风格{QColor color = penColorFrame->palette().color(QPalette::Window);int value = penWidthSpinBox->value();Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(styleValue, Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(), Qt::UserRole).toInt());Qt::PenJoinStyle join = Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(), Qt::UserRole).toInt());paintArea->setPen(QPen(color, value, style, cap, join));}void MainWindow::ShowPenCap(int capValue)//顶端风格{QColor color = penColorFrame->palette().color(QPalette::Window);int value = penWidthSpinBox->value();Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(), Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(capValue, Qt::UserRole).toInt());Qt::PenJoinStyle join = Qt::PenJoinStyle(penJoinComboBox->itemData(penJoinComboBox->currentIndex(), Qt::UserRole).toInt());paintArea->setPen(QPen(color, value, style, cap, join));}void MainWindow::ShowPenJoin(int joinValue)//画笔连接点风格{QColor color = penColorFrame->palette().color(QPalette::Window);int value = penWidthSpinBox->value();Qt::PenStyle style = Qt::PenStyle(penStyleComboBox->itemData(penStyleComboBox->currentIndex(), Qt::UserRole).toInt());Qt::PenCapStyle cap = Qt::PenCapStyle(penCapComboBox->itemData(penCapComboBox->currentIndex(), Qt::UserRole).toInt());Qt::PenJoinStyle join = Qt::PenJoinStyle(penJoinComboBox->itemData(joinValue, Qt::UserRole).toInt());paintArea->setPen(QPen(color, value, style, cap, join));}void MainWindow::ShowFill()//填充模式{Qt::FillRule fill = Qt::FillRule(fillComboBox->itemData(fillComboBox->currentIndex(), Qt::UserRole).toInt());paintArea->setFillRule(fill);}void MainWindow::ShowBrushColor()//画刷颜色{QColor color = QColorDialog::getColor(Qt::blue);brushColorFrame->setPalette(QPalette(color));ShowBrush(brushStyleComboBox->currentIndex());}void MainWindow::ShowBrush(int value)//画刷风格{QColor color = brushColorFrame->palette().color(QPalette::Window);//画刷当前的颜色Qt::BrushStyle style = Qt::BrushStyle(brushStyleComboBox->itemData(value, Qt::UserRole).toInt());//获取用户选择的画刷风格if (style == Qt::LinearGradientPattern)//线性渐变{QLinearGradient linearGradient(0, 0, 400, 400);//线性渐变的起止点位置linearGradient.setColorAt(0.0, Qt::white);//渐变比和渐变颜色linearGradient.setColorAt(0.2, color);linearGradient.setColorAt(1.0, Qt::black);paintArea->setBrush(linearGradient);}else if (style == Qt::RadialGradientPattern)//圆形渐变{QRadialGradient radialGradient(200, 200, 150, 150, 100);//中心点,半径,焦点radialGradient.setColorAt(0.0, Qt::white);radialGradient.setColorAt(0.2, color);radialGradient.setColorAt(1.0, Qt::black);paintArea->setBrush(radialGradient);}else if (style == Qt::ConicalGradientPattern)//锥形渐变{QConicalGradient conicalGradient(200, 200, 30);conicalGradient.setColorAt(0.0, Qt::white);conicalGradient.setColorAt(0.2, color);conicalGradient.setColorAt(1.0, Qt::black);paintArea->setBrush(conicalGradient);}else if (style == Qt::TexturePattern){paintArea->setBrush(QBrush(QPixmap("2.png")));}else{paintArea->setBrush(QBrush(color, style));}}MainWindow::~MainWindow(){}

MainWindow
这个类实际上就是显示界面的辅助类,要不你怎么操控呢,怎么查看呢。。。。

main.cpp

#include "painterarea.h"#include"mainwindow.h"#include <QtWidgets/QApplication>int main(int argc, char *argv[]){QApplication a(argc, argv);MainWindow w;w.show();return a.exec();}

参考:

http://blog.csdn.net/wushakun/article/details/49786445