基本概念
- QPainter 可以绘制简单的线条,复杂的形状,文本和贴图,并支持坐标变换
- QPainter 可以对继承 QPaintDevice 类的任何对象进行操作
- QPainter 最常见的用法是在 QWidget 的 paintEvent 中,构造和自定义 QPainter 对象,然后进行绘制
QPainter 用法
save(); // 保存状态
restore(); // 恢复状态
setPen(); // 设置线条
setBrush(); // 设置填充
setFont(); // 只对文字有效,设置字体
translate(); // 平移
rotate(); // 旋转
scale(); // 缩放
setRenderHinter(QPainter::Antialiasing, true); // 抗锯齿
QPainterPath 可以绘制路径
QPen 设置
- color,width,style,cap,join 等设置都包含在 QPen 中
- style,cap 和 join 等选项都在 Qt 命名空间中
其它注意事项
设置 QWidget 背景色
setAutoFillBackground(true);
setbackgroundRole(QPalette::Base);
QPixmap 载入图片
pixmap.load(path);
QComboBox 用法
comboBox->addItem("name", item);
comboBox->itemData(index, Qt::UserRole)
;
类型转换
- Qvariant 首先要用 toInt() 转化成成型,之后才能用 static_cast 转换成 enum class
布局
- layoutSizeConstraint 设置成 setMinimumSize 可以保持布局最小
案例代码
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QApplication> #include <QStyle> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; private slots: void shapeChanged(); void penChanged(); void brushChanged(); }; #endif // MAINWINDOW_H
mainwindow.cpp
mainwindow.cpp #include "mainwindow.h" #include "./ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); this->setWindowTitle("基本绘制"); this->setWindowIcon(qApp->style()->standardIcon(QStyle::SP_DialogHelpButton)); ui->comboBoxShape->addItem(tr("Polygon"), static_cast<int>(RenderArea::Shape::Polygon)); ui->comboBoxShape->addItem(tr("Rectangle"), static_cast<int>(RenderArea::Shape::Rect)); ui->comboBoxShape->addItem(tr("Rounded Rectangle"), static_cast<int>(RenderArea::Shape::RoundedRect)); ui->comboBoxShape->addItem(tr("Ellipse"), static_cast<int>(RenderArea::Shape::Ellipse)); ui->comboBoxShape->addItem(tr("Pie"), static_cast<int>(RenderArea::Shape::Pie)); ui->comboBoxShape->addItem(tr("Chord"), static_cast<int>(RenderArea::Shape::Chord)); ui->comboBoxShape->addItem(tr("Path"), static_cast<int>(RenderArea::Shape::Path)); ui->comboBoxShape->addItem(tr("Line"), static_cast<int>(RenderArea::Shape::Line)); ui->comboBoxShape->addItem(tr("Polyline"), static_cast<int>(RenderArea::Shape::Polyline)); ui->comboBoxShape->addItem(tr("Arc"), static_cast<int>(RenderArea::Shape::Arc)); ui->comboBoxShape->addItem(tr("Points"), static_cast<int>(RenderArea::Shape::Points)); ui->comboBoxShape->addItem(tr("Text"), static_cast<int>(RenderArea::Shape::Text)); ui->comboBoxShape->addItem(tr("Pixmap"), static_cast<int>(RenderArea::Shape::Pixmap)); ui->spinBoxPenWidth->setRange(0, 20); ui->spinBoxPenWidth->setSpecialValueText(tr("0 (cosmetic pen)")); ui->comboBoxPenSytle->addItem(tr("Solid"), static_cast<int>(Qt::SolidLine)); ui->comboBoxPenSytle->addItem(tr("Dash"), static_cast<int>(Qt::DashLine)); ui->comboBoxPenSytle->addItem(tr("Dot"), static_cast<int>(Qt::DotLine)); ui->comboBoxPenSytle->addItem(tr("Dash Dot"), static_cast<int>(Qt::DashDotLine)); ui->comboBoxPenSytle->addItem(tr("Dash Dot Dot"), static_cast<int>(Qt::DashDotDotLine)); ui->comboBoxPenSytle->addItem(tr("None"), static_cast<int>(Qt::NoPen)); ui->comboBoxPenCap->addItem(tr("Flat"), Qt::FlatCap); ui->comboBoxPenCap->addItem(tr("Square"), Qt::SquareCap); ui->comboBoxPenCap->addItem(tr("Round"), Qt::RoundCap); ui->comboBoxPenJoin->addItem(tr("Miter"), Qt::MiterJoin); ui->comboBoxPenJoin->addItem(tr("Bevel"), Qt::BevelJoin); ui->comboBoxPenJoin->addItem(tr("Round"), Qt::RoundJoin); ui->comboBoxBrushStyle->addItem(tr("Linear Gradient"), static_cast<int>(Qt::LinearGradientPattern)); ui->comboBoxBrushStyle->addItem(tr("Radial Gradient"), static_cast<int>(Qt::RadialGradientPattern)); ui->comboBoxBrushStyle->addItem(tr("Conical Gradient"), static_cast<int>(Qt::ConicalGradientPattern)); ui->comboBoxBrushStyle->addItem(tr("Texture"), static_cast<int>(Qt::TexturePattern)); ui->comboBoxBrushStyle->addItem(tr("Solid"), static_cast<int>(Qt::SolidPattern)); ui->comboBoxBrushStyle->addItem(tr("Horizontal"), static_cast<int>(Qt::HorPattern)); ui->comboBoxBrushStyle->addItem(tr("Vertical"), static_cast<int>(Qt::VerPattern)); ui->comboBoxBrushStyle->addItem(tr("Cross"), static_cast<int>(Qt::CrossPattern)); ui->comboBoxBrushStyle->addItem(tr("Backward Diagonal"), static_cast<int>(Qt::BDiagPattern)); ui->comboBoxBrushStyle->addItem(tr("Forward Diagonal"), static_cast<int>(Qt::FDiagPattern)); ui->comboBoxBrushStyle->addItem(tr("Diagonal Cross"), static_cast<int>(Qt::DiagCrossPattern)); ui->comboBoxBrushStyle->addItem(tr("Dense 1"), static_cast<int>(Qt::Dense1Pattern)); ui->comboBoxBrushStyle->addItem(tr("Dense 2"), static_cast<int>(Qt::Dense2Pattern)); ui->comboBoxBrushStyle->addItem(tr("Dense 3"), static_cast<int>(Qt::Dense3Pattern)); ui->comboBoxBrushStyle->addItem(tr("Dense 4"), static_cast<int>(Qt::Dense4Pattern)); ui->comboBoxBrushStyle->addItem(tr("Dense 5"), static_cast<int>(Qt::Dense5Pattern)); ui->comboBoxBrushStyle->addItem(tr("Dense 6"), static_cast<int>(Qt::Dense6Pattern)); ui->comboBoxBrushStyle->addItem(tr("Dense 7"), static_cast<int>(Qt::Dense7Pattern)); ui->comboBoxBrushStyle->addItem(tr("None"), static_cast<int>(Qt::NoBrush)); connect(ui->comboBoxShape, &QComboBox::activated, this, &MainWindow::shapeChanged); connect(ui->spinBoxPenWidth, &QSpinBox::valueChanged, this, &MainWindow::penChanged); connect(ui->comboBoxPenSytle, &QComboBox::activated, this, &MainWindow::penChanged); connect(ui->comboBoxPenCap, &QComboBox::activated, this, &MainWindow::penChanged); connect(ui->comboBoxPenJoin, &QComboBox::activated, this, &MainWindow::penChanged); connect(ui->comboBoxBrushStyle, &QComboBox::activated, this, &MainWindow::brushChanged); connect(ui->checkBoxAntiAliasing, &QAbstractButton::toggled, ui->renderArea, &RenderArea::setAntialiased); connect(ui->checkBoxTransformation, &QAbstractButton::toggled, ui->renderArea, &RenderArea::setTransformed); shapeChanged(); penChanged(); brushChanged(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::shapeChanged() { auto shape = static_cast<RenderArea::Shape>(ui->comboBoxShape->itemData( ui->comboBoxShape->currentIndex() ).toInt()); ui->renderArea->setShape(shape); } void MainWindow::penChanged() { int width = ui->spinBoxPenWidth->value(); auto style = static_cast<Qt::PenStyle>(ui->comboBoxPenSytle->itemData( ui->comboBoxPenSytle->currentIndex() ).toInt()); auto cap = static_cast<Qt::PenCapStyle>(ui->comboBoxPenCap->itemData( ui->comboBoxPenCap->currentIndex() ).toInt()); auto join = static_cast<Qt::PenJoinStyle>(ui->comboBoxPenJoin->itemData( ui->comboBoxPenJoin->currentIndex() ).toInt()); ui->renderArea->setPen(QPen(Qt::blue, width, style, cap, join)); } void MainWindow::brushChanged() { auto style = static_cast<Qt::BrushStyle>(ui->comboBoxBrushStyle->itemData( ui->comboBoxBrushStyle->currentIndex() ).toInt()); if (style == Qt::LinearGradientPattern) { QLinearGradient linearGradient(0, 0, 100, 100); linearGradient.setColorAt(0.0, Qt::white); linearGradient.setColorAt(0.2, Qt::green); linearGradient.setColorAt(1.0, Qt::black); ui->renderArea->setBrush(linearGradient); } else if (style == Qt::RadialGradientPattern) { QRadialGradient radialGradient(50, 50, 50, 70, 70); radialGradient.setColorAt(0.0, Qt::white); radialGradient.setColorAt(0.2, Qt::green); radialGradient.setColorAt(1.0, Qt::black); ui->renderArea->setBrush(radialGradient); } else if (style == Qt::ConicalGradientPattern) { QConicalGradient conicalGradient(50, 50, 150); conicalGradient.setColorAt(0.0, Qt::white); conicalGradient.setColorAt(0.2, Qt::green); conicalGradient.setColorAt(1.0, Qt::black); ui->renderArea->setBrush(conicalGradient); } else if (style == Qt::TexturePattern) { ui->renderArea->setBrush(QBrush(ui->renderArea->getPixmap())); } else { ui->renderArea->setBrush(QBrush(Qt::green, style)); } }
renderarea.h
renderarea.h #ifndef RENDERAREA_H #define RENDERAREA_H #include <QWidget> #include <QPen> #include <QPainterPath> #include <QPainter> namespace Ui { class RenderArea; } class RenderArea : public QWidget { Q_OBJECT public: explicit RenderArea(QWidget *parent = nullptr); ~RenderArea(); enum class Shape { Line, Points, Polyline, Polygon, Rect, RoundedRect, Arc, Ellipse, Chord, Pie, Path, Text, Pixmap, }; const QPixmap &getPixmap() const; public slots: void setShape(const Shape newShape); void setPen(const QPen &newPen); void setBrush(const QBrush &newBrush); void setAntialiased(bool newAntialiased); void setTransformed(bool newTransformed); private: Shape shape; QPen pen; QBrush brush; bool antialiased; bool transformed; QPixmap pixmap; Ui::RenderArea *ui; // QWidget interface protected: void paintEvent(QPaintEvent *event) override; }; #endif // RENDERAREA_H
renderarea.cpp
renderarea.cpp #include "renderarea.h" #include "ui_renderarea.h" RenderArea::RenderArea(QWidget *parent) : QWidget(parent), ui(new Ui::RenderArea) { ui->setupUi(this); setAutoFillBackground(true); setBackgroundRole(QPalette::Base); shape = Shape::Polygon; antialiased = false; transformed = false; pixmap.load(":/pixmap.jpg"); } RenderArea::~RenderArea() { delete ui; } void RenderArea::setShape(const Shape newShape) { shape = newShape; update(); } void RenderArea::setPen(const QPen &newPen) { pen = newPen; update(); } void RenderArea::setBrush(const QBrush &newBrush) { brush = newBrush; update(); } void RenderArea::setAntialiased(bool newAntialiased) { antialiased = newAntialiased; update(); } void RenderArea::setTransformed(bool newTransformed) { transformed = newTransformed; update(); } const QPixmap &RenderArea::getPixmap() const { return pixmap; } void RenderArea::paintEvent(QPaintEvent *event) { static const QPoint points[4] = { QPoint(10, 80), QPoint(20, 10), QPoint(80, 30), QPoint(90, 70) }; QRect rect(10, 20, 80, 60); QPainterPath path; path.moveTo(20, 80); path.lineTo(20, 30); path.cubicTo(80, 0, 50, 50, 80, 80); int startAngle = 20 * 16; int arcLength = 120 * 16; QPainter painter(this); painter.setPen(pen); painter.setBrush(brush); if (antialiased) { painter.setRenderHint(QPainter::Antialiasing, true); } for (int x = 0; x < width(); x += 100) { for (int y = 0; y < height(); y += 100) { painter.save(); painter.translate(x, y); if (transformed) { painter.translate(50, 50); painter.rotate(60.0); painter.scale(0.6, 0.9); painter.translate(-50, -50); } switch (shape) { case Shape::Line: painter.drawLine(rect.bottomLeft(), rect.topRight()); break; case Shape::Arc: painter.drawArc(rect, startAngle, arcLength); break; case Shape::Chord: painter.drawChord(rect, startAngle, arcLength); break; case Shape::Ellipse: painter.drawEllipse(rect); break; case Shape::Path: painter.drawPath(path); break; case Shape::Pie: painter.drawPie(rect, startAngle, arcLength); break; case Shape::Pixmap: painter.drawPixmap(10, 10, pixmap); break; case Shape::Points: painter.drawPoints(points, 4); break; case Shape::Polygon: painter.drawPolygon(points, 4); break; case Shape::Polyline: painter.drawPolyline(points, 4); break; case Shape::Rect: painter.drawRect(rect); break; case Shape::RoundedRect: painter.drawRoundedRect(rect, 25, 25, Qt::RelativeSize); break; case Shape::Text: painter.drawText(rect, Qt::AlignCenter, "安小静"); break; } painter.restore(); } } }