一、Qt 窗口API函数基础知识
在Qt窗口编程中,常用的API函数有:
- QWidget类的API函数:包括setWindowTitle()、resize()、move()、show()、hide()、setFixedSize()、setWindowFlags()等。
- QMainWindow类的API函数:包括setCentralWidget()、menuBar()、statusBar()、addToolBar()、setWindowTitle()等。
- QDialog类的API函数:包括setModal()、exec()、rejected()、accepted()等。
- QMessageBox类的API函数:包括information()、question()、warning()、critical()等。
- QFileDialog类的API函数:包括getOpenFileName()、getSaveFileName()、getExistingDirectory()等。
- QInputDialog类的API函数:包括getText()、getInt()、getItem()等。
- QDesktopWidget类的API函数:包括screen()、screenGeometry()、availableGeometry()等。
- QPalette类的API函数:包括setColor()、setBrush()、setPixmap()等。
- QPainter类的API函数:包括drawText()、drawPixmap()、drawLine()、drawRect()等。
- QGraphicsScene类的API函数:包括addLine()、addEllipse()、addRect()、addPixmap()等。
案例分析:实现下图功能
代码示例:
dialog.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QLabel> #include <QGridLayout> class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = nullptr); ~Dialog(); private: QGridLayout *glayout; // 布局 QLabel *labelgeometry; // 显示函数名称 QLabel *labelgeometryvalue; // 显示geometry函数获取值 QLabel *labelwidth; QLabel *labelwidthvalue; QLabel *labelheight; QLabel *labelheightvalue; QLabel *labelrect; QLabel *labelrectvalue; QLabel *labelsize; QLabel *labelsizevalue; // 窗口大小变化事件,通过此函数获取实时窗口的大小 void resizeEvent(QResizeEvent *); // 窗口移动事件,通过此函数获取实时窗口的位置 void moveEvent(QMoveEvent *); public: // 更新Label标签的值 void UpdateLabelFunc(); }; #endif // DIALOG_H
dialog.cpp
#include "dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent) { resize(300,150); setWindowTitle("Qt窗口常用的API位置函数测试"); // 布局 glayout=new QGridLayout(this); labelgeometry=new QLabel("函数geomery():"); labelgeometryvalue=new QLabel; labelwidth=new QLabel("函数width():"); labelwidthvalue=new QLabel; labelheight=new QLabel("函数height():"); labelheightvalue=new QLabel; labelrect=new QLabel("函数rect():"); labelrectvalue=new QLabel; labelsize=new QLabel("函数size():"); labelsizevalue=new QLabel; glayout->addWidget(labelgeometry,0,0); glayout->addWidget(labelgeometryvalue,0,1); glayout->addWidget(labelwidth,1,0); glayout->addWidget(labelwidthvalue,1,1); glayout->addWidget(labelheight,2,0); glayout->addWidget(labelheightvalue,2,1); glayout->addWidget(labelrect,3,0); glayout->addWidget(labelrectvalue,3,1); glayout->addWidget(labelsize,4,0); glayout->addWidget(labelsizevalue,4,1); UpdateLabelFunc(); // 调用更新Label标签的值 } Dialog::~Dialog() { } // 更新Label标签的值 void Dialog::UpdateLabelFunc() { QString strgeometry; // 专门存放geometry()函数的显示结果 QString str1,str2,str3,str4; strgeometry=str1.setNum(geometry().x())+","+str2.setNum(geometry().y())+","+ str3.setNum(geometry().width())+","+str4.setNum(geometry().height()); labelgeometryvalue->setText(strgeometry); //将获取的值展示到这个控件 QString strw,strh; labelwidthvalue->setText(strw.setNum(width())); labelheightvalue->setText(strh.setNum(height())); QString strrect; QString strrect1,strrect2,strrect3,strrect4; strrect=strrect1.setNum(rect().x())+","+strrect2.setNum(rect().y())+","+ strrect3.setNum(width())+","+strrect4.setNum(height()); labelrectvalue->setText(strrect); QString strsize; QString strsize1,strsize2; strsize=strsize1.setNum(size().width())+","+strsize2.setNum(size().height()); labelsizevalue->setText(strsize); } // 窗口大小变化事件,通过此函数获取实时窗口的大小 void Dialog::resizeEvent(QResizeEvent *) { UpdateLabelFunc(); } // 窗口移动事件,通过此函数获取实时窗口的位置 void Dialog::moveEvent(QMoveEvent *) { UpdateLabelFunc(); }
main.cpp
#include "dialog.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; w.show(); return a.exec(); }
二、Qt 绘图框架设计 (QPainter 绘制)
QPainter 是 Qt 框架中用于绘制图形元素的一个类。它提供了一组方法,可以在 QWidget 和 QImage 等 QPaintDevice 上绘制图形。QPainter 中的绘图指令包含绘制图形基础元素如点、线、矩形、圆弧,以及填充、描边和变换等操作。
使用 QPainter 前需要先创建一个 QPainter 对象,并指定要绘制的 QPaintDevice。然后,通过对 QPainter 对象调用不同的绘图方法实现所需绘图效果。
QPainter 除了提供基本的绘图操作外,还提供了一些高级的绘图操作,例如抗锯齿、渐变填充、绘制图片、文字、路径和定制化的绘制元素等。这些高级操作可以通过 QPainter 的不同成员函数进行调用。
QPainter 也是 Qt 绘图工具的一个基础,它被广泛应用于 Qt 图形用户界面(GUI)开发中,用于绘制自定义的控件、图表和各种特定的图形效果等。
案例分析:实现下图功能
代码示例:增加一个PainterArea类
painterarea.h
#ifndef PAINTERAREA_H #define PAINTERAREA_H #include <QWidget> // QPen 钢笔(画笔)是基本的图形对象,绘制直线、曲线、多边形等形状 #include <QPen> // QBrush 画刷是基本的图形对象,主要用于填充,比如矩形、多边形等形状 #include <QBrush> #include <QPainter> class PainterArea : public QWidget { Q_OBJECT public: explicit PainterArea(QWidget *parent = nullptr); // 绘制直线、长方形(矩形) enum shape{Line,Rectangle}; void setShape(shape); // 此函数实现绘制形状 void setPen(QPen); void setBrush(QBrush); void paintEvent(QPaintEvent *); // 重绘事件 void setfillrule(Qt::FillRule); // 填充规则 signals: public slots: private: shape shp; QPen pen; QBrush brsh; Qt::FillRule fillrle; }; #endif // PAINTERAREA_H
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include "painterarea.h" #include <QLabel> #include <QComboBox> #include <QGridLayout> #include <QColorDialog> class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: PainterArea *labelshapeArea; QLabel *labelshape; QComboBox *comboboxshape; QGridLayout *glayout; private slots: void dispShapeFunc(int); }; #endif // WIDGET_H
main.cpp
#include "widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
painterarea.cpp
#include "painterarea.h" PainterArea::PainterArea(QWidget *parent) : QWidget(parent) { setPalette(QPalette(Qt::red)); // 调色板来改变背景颜色 setAutoFillBackground(true); // Qt窗口是否需要绘制背景 // 设置最小尺寸 setMinimumSize(410,410); } void PainterArea::setShape(shape sh) // 此函数实现绘制形状 { shp=sh; update(); } void PainterArea::setPen(QPen sh) { pen=sh; update(); } void PainterArea::setBrush(QBrush sh) { brsh=sh; update(); } void PainterArea::paintEvent(QPaintEvent *) // 重绘事件 { QPainter p(this); p.setPen(pen); p.setBrush(brsh); QRect rect(55,110,290,180); switch (shp) { case Line: // 直线 p.drawLine(rect.topLeft(),rect.bottomRight()); break; case Rectangle: // 矩形 p.drawRect(rect); break; default: break; } } void PainterArea::setfillrule(Qt::FillRule rle) // 填充规则 { fillrle=rle; update(); // 重新绘制区域窗体 }
widget.cpp
#include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { labelshapeArea=new PainterArea; glayout=new QGridLayout; // 控制面板的布局 setWindowTitle("Qt绘图框架测试:QPainter类"); labelshape=new QLabel("绘制形状:"); //右边有一个下拉列表框 comboboxshape=new QComboBox; comboboxshape->addItem("Line",PainterArea::Line); comboboxshape->addItem("Rectangle",PainterArea::Rectangle); connect(comboboxshape,SIGNAL(activated(int)),this,SLOT(dispShapeFunc(int))); glayout->addWidget(labelshape,0,0); glayout->addWidget(comboboxshape,0,1); QHBoxLayout *mainlayout=new QHBoxLayout(this); // 整体布局 mainlayout->addWidget(labelshapeArea); // 向布局添加控件 mainlayout->addLayout(glayout); // 向整体布局添加布局 // 如下语句大家自己添加 dispShapeFunc(comboboxshape->currentIndex());//显示默认的图形 } Widget::~Widget() { } void Widget::dispShapeFunc(int v) { PainterArea::shape sp=PainterArea::shape(comboboxshape->itemData(v,Qt::UserRole).toInt()); labelshapeArea->setShape(sp); }
三、Qt 双缓冲机制
Qt双缓冲机制是一种优化技术,用于减少图形闪烁和提高图形性能,特别是在需要频繁重绘的情况下。
简单来说,双缓冲机制就是在一个缓冲区中进行图形绘制,然后将绘制好的图形复制到屏幕中显示,这样能够有效地减少图形闪烁的问题,并且提高了绘图的速度和效率。
在Qt中,双缓冲机制可以通过使用QPixmap或QImage来实现。具体的实现过程可以分为以下几个步骤:
- 创建一个QPixmap或QImage对象。
- 在该对象上进行绘图操作。
- 将绘制好的图像复制到屏幕中显示。
案例分析:绘图工具,可以选择线型、线宽及颜色等基本要素。QMainWindow 对象作为主窗口,QToolBar 对象作为工具栏,QWidget 对象作为主窗口的中央窗体 CentralWidget,也就是绘图区,如下图所示:
代码示例:增加一个DrawWidget类
drawwidget.h
#ifndef DRAWWIDGET_H #define DRAWWIDGET_H #include <QWidget> #include <QtGui> #include <QMouseEvent> // 鼠标事件 #include <QPaintEvent> // 绘制事件 #include <QResizeEvent> // 实时获取窗口操作等大小 #include <QColor> #include <QPixmap> // 显示图像 #include <QPainter> #include <QPalette> #include <QPen> class DrawWidget : public QWidget { Q_OBJECT public: explicit DrawWidget(QWidget *parent = nullptr); void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void paintEvent(QPaintEvent *); void resizeEvent(QResizeEvent *); signals: public slots: void setStyle(int); // 设置线风格 void setWidth(int); // 设置线宽度 void setColor(QColor); // 设置线颜色 void clearFunc(); // 清除函数 private: QPixmap *pix; // 在屏幕上显示图像而设计和优化 QPoint startpos; QPoint endPos; int style,widthss; QColor color; }; #endif // DRAWWIDGET_H
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QLabel> #include <QComboBox> #include <QToolButton> #include <QSpinBox> #include "drawwidget.h" #include <QGridLayout> #include <QColorDialog> #include <QToolBar> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); void CreateToolBarFunc(); // 创建工具条 private: DrawWidget *drawWidget; QGridLayout *glayout; QLabel *labelstyle; QComboBox *comboboxlabelstyle; QLabel *labelwidth; QSpinBox *spinboxlabelwidth; QToolButton *colorbutton; QToolButton *clearbutton; private slots: void dispstyle(); void dispcolor(); }; #endif // MAINWINDOW_H
drawwidget.cpp
#include "drawwidget.h" DrawWidget::DrawWidget(QWidget *parent) : QWidget(parent) { setAutoFillBackground(true); setPalette(QPalette(Qt::white)); pix=new QPixmap(size()); pix->fill(Qt::white); // 设置绘制区窗口最小尺寸 setMinimumSize(600,400); } void DrawWidget::setStyle(int s) // 设置线风格 { style=s; } void DrawWidget::setWidth(int w) // 设置线宽度 { widthss=w; } void DrawWidget::setColor(QColor c) // 设置线颜色 { color=c; } void DrawWidget::clearFunc() // 清除函数 { QPixmap *cPix=new QPixmap(size()); cPix->fill(Qt::white); pix=cPix; update(); } void DrawWidget::mousePressEvent(QMouseEvent *e) { startpos=e->pos(); } void DrawWidget::mouseMoveEvent(QMouseEvent *e) { QPainter *painter=new QPainter; QPen pen; pen.setStyle((Qt::PenStyle)style); pen.setWidth(widthss); pen.setColor(color); painter->begin(pix); painter->setPen(pen); painter->drawLine(startpos,e->pos()); painter->end(); startpos=e->pos(); update(); } void DrawWidget::paintEvent(QPaintEvent *) { QPainter painter(this); painter.drawPixmap(QPoint(0,0),*pix); } void DrawWidget::resizeEvent(QResizeEvent *event) { if(height()>pix->height() || width()>pix->width()) { QPixmap *newPix=new QPixmap(size()); newPix->fill(Qt::white); QPainter ps(newPix); ps.drawPixmap(QPoint(0,0),*pix); pix=newPix; } QWidget::resizeEvent(event); }
main.cpp
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindow.cpp
#include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle("图形绘制综合案例分析(双缓冲机制)"); drawWidget=new DrawWidget; setCentralWidget(drawWidget); // 将刚才创建对象作为主窗口的中心窗口 CreateToolBarFunc(); // 调用此函数实现创建工具栏 setMinimumSize(600,400); dispstyle(); drawWidget->setWidth(spinboxlabelwidth->value()); // 初始化线宽度 drawWidget->setColor(Qt::black); // 初始化线颜色 } MainWindow::~MainWindow() { } void MainWindow::CreateToolBarFunc() // 创建工具条 { QToolBar *toolBar=addToolBar("Tool"); labelstyle=new QLabel("线型风格:"); comboboxlabelstyle=new QComboBox; comboboxlabelstyle->addItem("SolidLine",static_cast<int>(Qt::SolidLine)); // 实线 comboboxlabelstyle->addItem("DashLine",static_cast<int>(Qt::DashLine)); // comboboxlabelstyle->addItem("DashDotDotLine",static_cast<int>(Qt::DashDotDotLine)); comboboxlabelstyle->addItem("DotLine",static_cast<int>(Qt::DotLine)); // 虚线 // 为什么不出现虚线?activeated改为activated connect(comboboxlabelstyle,SIGNAL(activated(int)),this,SLOT(dispstyle())); labelwidth=new QLabel("线型宽度:"); spinboxlabelwidth=new QSpinBox; connect(spinboxlabelwidth,SIGNAL(valueChanged(int)),drawWidget,SLOT(setWidth(int))); colorbutton=new QToolButton; QPixmap pixmap(20,20); pixmap.fill(Qt::black); colorbutton->setIcon(QIcon(pixmap)); connect(colorbutton,SIGNAL(clicked()),this,SLOT(dispcolor())); clearbutton=new QToolButton; clearbutton->setText("清除绘制"); connect(clearbutton,SIGNAL(clicked()),drawWidget,SLOT(clearFunc())); toolBar->addWidget(labelstyle); toolBar->addWidget(comboboxlabelstyle); toolBar->addWidget(labelwidth); toolBar->addWidget(spinboxlabelwidth); toolBar->addWidget(colorbutton); toolBar->addWidget(clearbutton); } void MainWindow::dispstyle() { drawWidget->setStyle(comboboxlabelstyle->itemData(comboboxlabelstyle->currentIndex(), Qt::UserRole).toInt()); } void MainWindow::dispcolor() { QColor color=QColorDialog::getColor(static_cast<int>(Qt::black),this); if(color.isValid()) { drawWidget->setColor(color); QPixmap ps(20,20); ps.fill(color); } }