一、概述
1.1概念
跨平台的C++图形用户界面应用程序框架
常见GUI:Qt/MFC
1.2发展史
1991-
1.3支持平台
windows
unix/linux
macos
嵌入式平台
1.4优点
跨平台、接口简单、效率高...
1.5案例
咪咕音乐、WPS
1.6QtCreator
QT:开发工具包
QtCreator:集成编译器,Qt的桌面环境

欢迎选项:
工程:创建工程+打开工程
示例:demo程序,下载运行研读源码
教程
编辑选项:
编辑项目文件
设计选项:
设计ui
debug选项:调试
项目设置选项:
帮助选项:
查询
二、创建qt项目
创建项目:
方式1:欢迎-project-new project
方式2:菜单栏-文件-新建文件或项目
打开项目(页面上不存在):
方式1:欢迎-project-open project
方式2:菜单栏-文件-打开文件或项目
创建项目注意:
1.项目名称一般不要用特殊符号,不要用中文
2.项目工程保存路径可修改,路径不要带中文
3.创建类的基类:带菜单栏的窗口、空白窗口、对话栏窗口
4.创建类的类名首字母要大写
5.首次创建项目,ui不使用
main.cpp
#include "widget.h"//Qt中一个类对应一个头文件,类名就是头文件名
#include <QApplication>//Qt系统提供的标准类名声明头文件
int main(int argc, char *argv[])
{
QApplication a(argc, argv);//应用程序类(整个后台管理命脉,处理应用程序的初始化和结束,事件处理调度,注意不管我们有多少窗口,一个Application类就可)
Widget w;//实例化对象,调用构造函数
w.show();//显示图形界面
return a.exec();//主事件循坏,在exe函数中,Qt接受并处理用户和系统的时间并且将他们传递给适当的窗口控件
}
widget.cpp
include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{}
Widget::~Widget() {}
1确定代码书写位置
main.cpp:主函数
widget.cpp:类的函数
一般情况,窗口属性和添加和对控件的操作都会在类的构造函数中书写。
优点:可以让主程序中无多余代码
widget.h:类和头文件
2确定使用哪些函数

索引-对应的类-
类的说明(类的头文件、组件、基类、派生类)
注意:如果函数在类中没有找到,可以在基类中找
3设置窗口属性
//修改窗口的标题(第一个窗口)
this->setWindowTitle("第一个窗口");
//设置窗口大小,设置完成可以拉伸
this->resize(100,100);
//设置固定大小,设置完成不可拉伸
三、创建第一个按钮
1:包含头文件及模块#include<QPushButton> QT += widgets
2:调用类的构造函数创建按钮
QPushButton *button=new QPushButton;
3.显示按钮
//button->show();
//设置按钮父对象为窗口
button->setParent(this);
2按钮属性设置
//设置按钮内容
button->setText("第一个按钮");
//设置按钮显示位置
button->move(100,100);
//设置按钮大小
button->setFixedSize(400,400);
3两种创建按钮方式的区别
QPushButton *button2=new QPushButton("第二个按钮",this);
this->resize(600,400);
方式1:窗口默认大小,按钮显示在左上角
方式2:窗口按照按钮大小来创建
4对象树
概念:QT对象间父子关系
一定程度上解决了内存问题
举例:自定义按钮类继承QPushButton,自定义按钮类,并将其添加窗口类,实现构造与析构,然后关闭窗口,看析构函数是否自动执行
使用注意:构造指定parent对象,在堆上创建
该段代码无问题:因为栈一般先构造的后析构,下面程序是先析构button,同时将button从window的子对象列表删除
然后析构window,仅析构window(window无子对象)
QWidget window;
QPushButton button=QPushButton("退出",&window);
代码有问题:
QPushButton quit("Quit");
QWidget window;
quit.setParent(&window);
5Qt窗口坐标体系
窗口左上角为原点,X向右增大,Y向下增大
四、信号和槽机制
1介绍
2connet 函数使用
connet(sender,signal,receiver,slot);
参数:
1.信号发出者
2.信号
3.信号的接受者
4.接受到信号执行任务(槽函数)
//创建按钮
QPushButton *button=new QPushButton("点击关闭窗口",this);
this->resize(600,400);
//信号与槽
connect(button,&QPushButton::clicked,this,&Widget::close);

3自定义信号与槽
步骤1:确定场景
老师饿了,学生请客
小哥敲门,家人开门
步骤2:添加两个类
步骤3:在老师类中声明信号+在学生类在声明并实现槽函数
teacher.h(信号:一般在signals里面写,返回值void,参数可以存在,仅声明不需要实现,可以重载)
signals:
void hungury();
student.h(槽函数:一般在public slots里面写,返回值void,参数可以存在,需要声明并实现,可以重载)
public slots:
void treat();
student.cpp
#include<QDebug>
Student::Student(QObject *parent)
: QObject{parent}
{
}
void Student::treat()
{
qDebug()<<"请老师吃饭";
}
步骤4:创建信号+信号与槽连接
this->tea=new Teacher();
this->stu=new Student();
connet(tea,&Teacher::hungury,stu,&Student::treat);
步骤5:触发信号
(widget.h)声明触发信号的成员函数
void ClasOsver();
(widget.cpp)定义出发信号的成员函数+调用成员函数
ClasOsver();
void Widget::ClasOsver(){
emit tea->hungury();
}

点击按钮请吃饭
方式一: connect(button,&QPushButton::clicked,this,&Widget::ClasOsver);
方式二:信号连接信号
connect(button,&QPushButton::clicked,tea,&Teacher::hungury);

4重载自定义信号与槽
步骤1:重新写信号声明(带参数)teacher.h
void hungury(QString food);
步骤2:重新写槽函数声明及定义(带参数)student.h
void treat(QString food);
void Student::treat(QString food)student.cpp
{
qDebug()<<"请老师吃饭"<<food;
}
步骤3:由于函数重载,所以需要函数指针指向函数地址,然后再做连接widget.h
void (Teacher::*teachersignal)(QString)=&Teacher::hungury;
void (Student::*studentslot)(QString)=&Student::treat;
connect(tea,teachersignal,stu,studentslot);


5 信号与槽总结
1.发送者与接受者需要是QObject的子类(槽函数全局,lambda除外)
2.信号与槽函数返回值都是void
3.信号需要声明不需要定义实现,槽函数需要声明并实现
4.槽函数是普通的成员函数,作为成员函数,会受到public、private、protected的影响
5.使用emit在恰当的位置发送信号;
6.使用connect()函数连接信号和槽。
7.任何成员函数、static函数、全局函数和Lambda表达式都可以作为槽函数。
8.信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。
如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数在的那些参数的顺序也必须和信号的前面几个致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少)。
举例:signal(QSting)和slot (QSting)
拓展:1.信号与槽对应可以一对一,一对多(发出信号,槽函数一个个执行,顺序不确定),多对一(任意信号发出,槽函数都会执行)
2.信号可以连接信号
3.槽可以被断开链接(disconnect),也可以被取消链接(当一个对象delect了,取消这个对象上的槽)
4.使用c++11中的lambda表达式
五、lambda表达式
概念:c++11中的lambda表达式用于定义并创建匿名的函数对象,以简化编程工作
语法:[capture](parameters)mutable->return-type{statement}
1.[]是引出符,capture捕获列表,捕获的是上下文的变量
2.(parameters)参数列表,与普通函数的参数列表一致。
3.mutable可修改标识符,按值传递函数对象参数时(默认仅读权限),加上mutable修饰符后,可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)
4.->return-type返回值类型
5.{statement}函数体,内容与普通函数一致。
注意1.[]标识一个Lambda的开始,这部分必须存在,不能省略
空。 没有使用任何函数对象参数
= 函数体内可以使用Lambda所在范围内所以可见的局部变量,值传递
& 函数体内可以使用Lambda所在范围内所以可见的局部变量,引用传递
a 将a按值进行传递
&a 将a按地址进行传递
2.()参数列表,如果不需要传递参数,()可以一同省略
3.如果使用mutable,参数列表()不能省略的即使参数为空;如果使用mutable,修改拷贝,而不是值本身
4.返回值类型,如果不需要,可省略
5.{函数体},可以使用参数列表,也可以使用捕获列表
[](){
qDebug()<<"lambda is running!";
}();---------------------------------------------------------------
auto fun=[](){
qDebug()<<"lambda is running!";
};fun();

auto fun=[](int a,int b){
qDebug()<<"lambda is running!";
return a+b;
};
int sum=fun(100,200);
qDebug()<<sum;
}

如果无mutable ,会报错
int m=10;
auto fun=[m](int a,int b)mutable{
qDebug()<<"lambda is running!";
m=300;
return a+b;
};
int sum=fun(100,200);
qDebug()<<sum;
}

3.槽函数一般用lambda表达式
QPushButton *myBtn=new QPushButton("点击",this);
this->resize(600,400);
connect(myBtn,&QPushButton::clicked,this,[=](){
qDebug()<<"按钮被按下";
}
);

六、QMainWindow
1概述
为用户提供主窗口程序的类
菜单栏
![]()
工具栏
![]()
![]()
状态栏
![]()
2菜单栏
菜单栏类QMenuBar:
菜单类QMenu:
QAction类:充当子菜单(菜单项)
#include<QMenuBar>
#include<QMenu>
#include<QAction>//创建菜单栏
QMenuBar *menubar=new QMenuBar(this);
this->setMenuBar(menubar);
//创建菜单
QMenu *menu1=new QMenu("文件");
QMenu *menu2=new QMenu("编辑");
QMenu *menu3=new QMenu("构建");
menubar->addMenu(menu1);
menubar->addMenu(menu2);
menubar->addMenu(menu3);

resize(800,600);
//创建菜单栏
QMenuBar *menubar=new QMenuBar(this);
this->setMenuBar(menubar);
//创建菜单
QMenu *menu1=new QMenu("文件");
QMenu *menu2=new QMenu("编辑");
QMenu *menu3=new QMenu("构建");
menubar->addMenu(menu1);
menubar->addMenu(menu2);
menubar->addMenu(menu3);
//创建菜单项
QAction *act1=new QAction("打开文件");
QAction *act2=new QAction("另存为");
QAction *act3=new QAction("关闭文件");
menu1->addAction(act1);
menu1->addAction(act2);
menu1->addAction(act3);

补充:
另一种创建菜单栏的方式(成员函数)
QMenuBar *menubar=menuBar();
点击菜单项,实现对应功能
connect(act3,&QAction::triggered,this,&QMainWindow::close);
3工具栏
工具栏类QToolBar:
QAction类:充当子工具(工具项)
//创建工具栏
QToolBar *toolbar=new QToolBar(this);
//this->addToolBar(toolbar);
this->addToolBar(Qt::LeftToolBarArea,toolbar);
QAction *act4=new QAction("工具");
toolbar->addAction(act1);
toolbar->addAction(act2);
toolbar->addAction(act3);
toolbar->addAction(act4);
//使用setAllowedAreas()函数指定停靠区域
toolbar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);
//修改工具栏不能移动(默认可上下左右移动)
//toolbar->setMovable(false);
//设置工具栏的浮动状态,(默认可悬浮窗口)
toolbar->setFloatable(false);
4状态栏
状态栏QStatusBar:#include<QLabel>
//创建状态栏
QStatusBar *statusbar=statusBar();
//QStatusBar *statusbar=new statusBar(this);
this->setStatusBar(statusbar);//增加临时信息
//statusbar->showMessage("页面显示成功",3000);
//增加正式信息(一般位于状态栏左侧)
QLabel *label1=new QLabel("打开文件",this);
statusbar->addWidget(label1);
//增加永久信息(一般位于状态栏右侧)
QLabel *label2=new QLabel("www.qf.com",this);
statusbar->addPermanentWidget(label2);
状态栏信息分类:
临时信息
正式信息
永久信息

5铆接部件(浮动窗口)
#include<QDockWidget>
//创建铆接部件
QDockWidget *dockwidget=new QDockWidget("first",this);
this->addDockWidget(Qt::TopDockWidgetArea,dockwidget);

6核心部件(中心部件)
#include<QTextEdit>
//创建记事本作为核心部件
QTextEdit *edit=new QTextEdit("文本编辑器",this);
this->setCentralWidget(edit);

7资源文件
qt资源系统是一个跨平台的资源机制,用于将程序运行时所需要的资源以二进制的形式存储与可执行文件内部。
加载资源:
步骤1:新增资源文件(右键工程新增资源文件)
步骤2:给资源文件增加前缀
步骤3:给资源文件增加资源(图片)
步骤4:起别名(选用)
1.给菜单项加载图片
//创建图片控件
QPixmap pix;
//选择图片
pix.load(":/open");
//给菜单项设置图片
act1->setIcon(QIcon(pix));

2.增加背景图
this->setFixedSize(800,600);
this->setAutoFillBackground(true);
//创建图片控件
QPixmap pix=QPixmap(":/open").scaled(this->size());
pix.load(":/open");
QPalette palette;
palette.setBrush(QPalette::Window,QBrush(pix));
this->setPalette(palette);

七、ui功能
ui功能:绘制界面(通过拖拽)

布局、固定弹簧、按钮、列表视图、容器、输入窗、显示窗
打开文件
关闭文件
另存为
this->resize(800.600);
ui->setupUi(this);
ui->statusBar->showMessage("页面显示成功".3000);
八、对话框
1.概述
分类:模态对话框:会阻塞同一应用程序中其他窗口的输入
非模态对话框:不会阻塞同一应用程序中其他窗口的输入
2.自定义对话框
模态对话框:#include<qdialog.h>
ui->setupUi(this);
QDialog dialog;
dialog.setWindowTitle(tr("Hello,dialog!"));
dialog.exec();
非模态对话框:
注意:1.对话框要在堆上创建
2.由于对话框独立,要独立释放
QDialog *dialog=new QDialog;
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setWindowTitle(tr("Hello,dialog!"));
dialog->show();
3.标准对话框
概念:QT内置的一系列对话框
#include<QDialog>
#include<QFileDialog>
#include<QDebug>void MainWindow::on_pushButton_clicked()
{
QString fileName=QFileDialog::getOpenFileName(this,tr("打开文件"),"./",tr("Images(*.png*.xpm*.jpg);;Text(*.txt)"));
if(!fileName.isEmpty())
ui->textEdit->append(fileName);
}
void MainWindow::on_pushButton_2_clicked()
{
QStringList fileName=QFileDialog::getOpenFileNames(this,"打开文件","./","Images(*.png*.xpm*.jpg)");
for(int i=0;i<fileName.count();i++)
{
qDebug()<<fileName.at(i);
}
}

总结:1.文件对话框使用,参考帮助文档
2.getOpenFileName,getOpenFileNames参数:父类对象指针,文件对话框的标题,打开文件路径,文件过滤器
3.文件过滤器写法: Images(*.png*.xpm*.jpg)
Images(*.png*.xpm*.jpg);;Text(*.txt)"
4.颜色对话框
QColorDialog::getColor生成颜色对话框
//点击按钮,生成颜色对话框,选择颜色,设置编辑器字体颜色
QPalette pal=ui->textEdit->palette();//获取现有palette
QColor iniColor=pal.color(QPalette::Text);//现有文字颜色
QColor color=QColorDialog::getColor(iniColor,this,"选择颜色");
//判断选择颜色是否有效,如果有效设置编辑器字体颜色
if(color.isValid()){
pal.setColor(QPalette::Text,color);
ui->textEdit->setPalette(pal);
总结:1.颜色对话框使用参考帮助文档
2.getColor生成颜色对话框,返回值是一个颜色变量,如果在颜色对话框选择取消,返回值无效,反之有效
5.字体对话框
QFontDialog::getFont生成选择字体的对话框
bool ok;
QFont iniFont=ui->textEdit->font();
QFont font=QFontDialog::getFont(&ok,QFont("Times",12),this);
if(ok)//如果OK=true
{
ui->textEdit->setFont(font);}else{
}

总结:1.字体对话框使用参考帮助文档
2.getFont生成字体对话框,不能通过返回值判断有效,一般是根据getFont的第一个参数逻辑变量是否为true
6.消息对话框
//错误弹窗
// QMessageBox::critical(this,"critical错误消息对话框","程序出现错误");
//警告弹窗
//QMessageBox::warning(this,"警告消息对话框","程序出现警告");
//消息弹窗
//QMessageBox::information(this,"消息对话框","程序一切正常",QMessageBox::Ok,QMessageBox::NoButton);
//消息选择弹窗
QMessageBox::StandardButton result;
result= QMessageBox::question(this,"选择信息框","文件已修改,是否保存",QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,QMessageBox::NoButton);
if(result==QMessageBox::Yes)
qDebug()<<"正在保存";
else if(result==QMessageBox::No)
qDebug()<<"不保存";
else
qDebug()<<"取消操作";



7.输入对话框
QInputDialog::输入文本
//生成输入文字对话框
bool ok;
QString text=QInputDialog::getText(this,tr("输入文字对话框"),tr("请输入文字"),QLineEdit::Normal,"demo",&ok);
if(ok&&!text.isEmpty())
ui->textEdit->append(text);

九、布局管理器
Qt提供了两种组件定位机制:绝对定位和布局定位
绝对定位:需要提供组件的长高,坐标值
布局定位:需要指定使用哪种布局(垂直、水平、网状、表格)
布局分类:系统自带的四种布局,一般不使用
widget中的四种布局,一般使用


1.登录功能
登录界面绘制 
ui->setupUi(this);
this->new_window=new Form();
connect(ui->pushButton,&QPushButton::clicked,this,[=](){
this->hide();
this->new_window->show();
});
connect(this->new_window,&Form::back,this,[=](){
this->new_window->hide();
this->show();}
);
}
十、QLabel创建及设置文本html
1.QLabel使用
方式1:代码
QLabel *label=new QLabel(this);
方式2:拖拽
ui->setupUi(this);
QLabel *label=new QLabel(this);
label->setText("这是代码创建的标签");
ui->label->setText("这是一个ui创建的标签");
显示文字/html



2. 设置图片
QPixmap pixmap;
pixmap.load(":/image/a.jpg");ui->label_image->setPixmap(pixmap);
3.设置动图
//显示动画
QMovie *movie=new QMovie(":/image/mario.gif");
ui->label_gif->setMovie(movie);
movie->start();
connect(ui->pushButton,&QPushButton::clicked,this,[=](){
movie->stop;
});
2.QLineEdit
ui->setupUi(this);
QLineEdit *edit=new QLineEdit(this);
edit->setText("这是代码创建的编辑框");//输入模式
QString str=ui->lineEdit->text();
qDebug()<<str;//密码模式
ui->lineEdit->setEchoMode(QLineEdit::Password);


3自定义控件
一般是重复性使用的窗口或者窗口中的模块。
解决问题:将许多重复性使用的窗口或者窗口中的模块封装成自定义控件,可以减少创建次数,仅创建一次,使用提升。
connect(ui->spinBox,SIGAL(valueChanged(int)),ui->horizontalSlider,SLOT(setValue(int)));
connect(ui->horizontalSlider,SIGNAL(valueChanged(int)),ui->spinBox,SLOT(setValue(int)));
4栈容器的使用
十一、QT消息机制和事件
事件:事件派发-》事件过滤器-》事件分发-》事件处理阶段
事件:系统或者QT本身在不同的时刻发出的
事件循环开始:exec()函数

1窗口关闭重设大小事件函数
步骤1:新增一个类继承与QWidget(新建工程)
步骤2:子类.h声明重写的函数
protected:
void closeEvent(QCloseEvent *event);
void resizeEvent(QResizeEvent *event);
步骤3:子类.cpp实现事件函数
void Widget::closeEvent(QCloseEvent *event)
{
int ret= QMessageBox::question(this,"提示""您确定要关闭窗口吗?");
if(ret==QMessageBox::Yes)
{
event->accept();
}
else{
event->ignore();
}
}
void Widget::resizeEvent(QResizeEvent *event)
{
qDebug()<<"oldsize="<<event->oldSize();
qDebug()<<"newsize="<<event->size();
}
2鼠标点击、释放、移动事件
步骤1:新建一个label类继承QWidget(新建工程,ui绘制label,新增c++类继承QWidget,代码修改继承QLabel,ui绘制label提升新建label类)
步骤2:查看帮助文档
步骤3:在mylabel.h声明事件函数
protected:
void mousePressEvent(QMouseEvent *ev);
void mouseReleaseEvent(QMouseEvent *ev);
void mouseMoveEvent(QMouseEvent *ev);
步骤4:在mylabei.cpp实现事件函数
MyLabel::MyLabel(QWidget *parent):QLabel(parent)
{
this->setMouseTracking(true);}
void MyLabel::mousePressEvent(QMouseEvent *ev)
{if(ev->button()==Qt::LeftButton){
qDebug()<<"鼠标左键被按下了";
}
else if(ev->button()==Qt::RightButton){
qDebug()<<"鼠标右键被按下了";
}
else{
qDebug()<<"鼠标其他按下了";
}
}
void MyLabel::mouseReseaseEvent(QMouseEvent *ev)
{
qDebug()<<"标签上鼠标被释放了";
}
void MyLabel::mouseMoveEvent(QMouseEvent *ev)
{
qDebug()<<"鼠标被移动了"<<ev->x()<<","<<ev->y();
}
3重写事件分发函数监听按键
案例:bool Widget::event(QEvent *event)
{
//判断事件类型(键盘事件)
if(event->type()==QEvent::KeyPress){
//将QEvent类型的event转换类型为QKeyEvent
QKeyEvent *keyEvent=ststic_cast<QKeyEvent*>(event);
if(keyEvent->key()==Qt::Key_Tab){
qDebug()<<"TAB被按下";
return true;
}
}
return QWidget::event(e);
}
{
//判断事件类型(键盘事件)
if(event->type()==QEvent::KeyPress){
//将QEvent类型的event转换类型为QKeyEvent
QKeyEvent *keyEvent=ststic_cast<QKeyEvent*>(event);
if(keyEvent->key()==Qt::Key_Tab){
qDebug()<<"TAB被按下";
return true;
}
}
return QWidget::event(e);
}
步骤1:,h声明event
bool event(QEvent *event);
步骤2:.cpp实现event
bool Widget::event(QEvent *event)
{
//判断事件类型(键盘事件)
if(event->type()==QEvent::KeyPress){
//将QEvent类型的event转换类型为QKeyEvent
QKeyEvent *keyEvent=ststic_cast<QKeyEvent*>(event);
if(keyEvent->key()==Qt::Key_Tab){
qDebug()<<"TAB被按下";
return true;
}
}
return QWidget::event(e);
}
{
//判断事件类型(键盘事件)
if(event->type()==QEvent::KeyPress){
//将QEvent类型的event转换类型为QKeyEvent
QKeyEvent *keyEvent=ststic_cast<QKeyEvent*>(event);
if(keyEvent->key()==Qt::Key_Tab){
qDebug()<<"TAB被按下";
return true;
}
}
return QWidget::event(e);
}
注意:返回值为bool
4事件过滤器(很少重写)
使用:重写
步骤1:声明
virtual bool QObject::eventFilter(QObject *watched,QEvent *event):
步骤2:实现(先判断是否是要过滤事件的组件,如果是,再去判断事件是否过滤,如果过滤返回true,如果不过滤返回false;)
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
i f ( o b j = t e x t E d i t )
i f ( e v e n t - > t y p e ( ) = Q E v e n t : K e y p r e s s ) {
QKeyEven * k e y E v e n t =s t a t i c _ c a s t < Q K e y E V e
nt* > ( e v e n t );
q D e b u g ( ) <<"Ate key press"<<k e y E v e n t->k e y ( ) ;
return true;
}else{
return false;
}else {
// pass the event on to the parent class
return QMainWindow: :eventFilter(obj,event);}
}
步骤3:安装
void QObject::installEventFilter(QObject * filterObj)
步骤4:移除
void QObject::removeEventFilter(QObject *filterObj)
5总结
事件处理有以下四个过程:
事件处理:重写鼠标按下事件、鼠标释放事件,这个是最简单的形式及功能。
事件分发:重新event函数。
事件过滤:重写eventFilter,过滤特定对象的事件I或者所有对象的所有事件(QCoreApplication::instance)。
事件派发:(QCoreApplication::notify)
十二、画笔使用
PPainter:画笔
QPainterDevice:绘图设备(纸张、墙壁)
QPaintEngine:画笔(QPainter)在不同的设备上进行绘制的统一的接口(一般不考虑)
void Widget::paintEvent(QPaintEvent *p){//页面加载,update
QPainter painter(this);
painter,drawLine(80,100,500,500);
painter,setPen(Qt::red);
painter,drawRect(0,0,400,200);
painter,setPen(QPen(Qt::blue,5));
painter,drawEllipse(0,0,400,200);
}
绘图设备
常见的绘图设备:
QPixmap专门为图像在屏幕上的显示做了优化
QBitmap是QPixmap的一个子类,它的色深限定为1,可以使用QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QBitmap。
QImage专门为图像的像素级访问做了优化。
QPicture则可以记录重现QPainter的各条命令。






1483

被折叠的 条评论
为什么被折叠?



