注意:两个路径都不能有中文
类信息:
例:btn -> show(); //show是以顶层方式弹出窗口控件
//让btn对象 依赖在 myWidget窗口中(父窗口)
btn->setParent(this);
按钮控件需要添加头文件 #include
QPushButton * btn = new QPushButton;
setParent(this); //当前类(当前窗口),所以this
setText(“文字”)
move(宽,高)
resize
setWindowTitle
setFixedSize
析构的顺序与创建的顺序相反
析构函数qDebug()打印的时候的顺序与实际析构顺序相反
(1)当创建的对象在堆区时候,如果指定的父亲是QObject派生下来的类或者QObject子类派生下来的类,可以不用管理释放的操作,将对象会放入到对象树中。
(2)一定程度上简化了内存回收机制(就是对象树)
技巧:
以后就可以大胆的在堆区(这里指在firstwidget的构造函数中)创建对象,
并将对象
myBtn -> setParent(this);
设置到对象树中,即可。到时候这个对象就会被自动析构,不用手动操作。
注意:尽量在构造子类对象的时候就同时指定parent对象,这样如果先析构parent对象,这个时候就不会出现二次析构问题,就可以在析构parent对象的同时完全把子类对象析构了。
对于嵌套窗口,其坐标是相对于父窗口来说的。
对象将想要处理的信号和自己的一个函数(即“槽”)绑定,来处理这个信号。
也就是说,当信号发出时,被连接的槽函数会自动被回调。
//信号与槽机制
//需求 点击我的按钮 关闭窗口
//参数1:信号的发送者; 参数2:发送的信号(函数的地址); 参数3:信号的接受者; 参数4:处理的槽函数(函数地址)
//connect(myBtn, &mypushbutton::clicked, this, &firstwidget::close);//这样写也可以(子类/父类)
connect( myBtn, &QPushButton::clicked, this, &QWidget::close );
创建文件之后的默认代码,此时将自定义信号写在signals下
发送者和接收者都需要是QObject的子类(当然,槽函数是 全局函数、Lambda 表达式等无需接收者的时候除外);
信号和槽函数返回值是 void(信号和槽都可以有参数)
信号只需要声明,不需要实现
槽函数需要声明也需要实现(槽函数可以写到 public slot 下,也可以写在 public 下 (高低版本差异))
槽函数是普通的成员函数,作为成员函数,会受到 public、private、protected 的影响;
使用 emit 在恰当的位置发送信号;
使用connect()函数连接信号和槽。
任何成员函数、static 函数、全局函数和 Lambda 表达式都可以作为槽函数
信号槽要求信号和槽的参数一致,所谓一致,是参数类型一致。
如果信号和槽的参数不一致,允许的情况是,槽函数的参数可以比信号的少,即便如此,槽函数存在的那些参数的顺序也必须和信号的前面几个一致起来。这是因为,你可以在槽函数中选择忽略信号传来的数据(也就是槽函数的参数比信号的少)。
带参的和不带参的函数地址都一样,所以对于带参的函数重载需要重新写一个连接connect
void( Teacher:: * tSignal )( QString ) = &Teacher::hungry;
.ToUtf8()
转为 QByteArray.Data()
转为 Char *点击按钮,触发下课:(注意语法)
connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);
注意:
click是槽
clicked是信号
断开信号 disconnect
<1>信号可以连接信号
<2>一个信号可以连接多个槽函数
<3>多个信号可以连接同一个槽函数
<4>信号和槽函数的参数必须类型一一对应
<5>信号的参数个数可以多于槽函数的参数个数(但是也要保证类型一一对应,注意顺序)
(信号的参数可以比槽函数多,可以理解为,A发出信号,但是接收方B不想理。
但是反过来不行,接收方B想要的参数,发送方A必须给,否则报错)
了解:
//Qt4版本以前的信号和槽连接方式
//利用Qt4信号槽 连接无参版本
//Qt4版本 底层SIGNAL(“hungry”) SLOT( “treat”)
connect(zt,SIGNAL(hungry()) , st , SLOT(treat()));
//Qt4版本优点:参数直观,缺点 :编译器对类型不做检测
//Qt5以上 支持 Qt4的版本写法,反之不支持
C++11中的Lambda表达式用于定义并创建匿名的函数对象,以简化编程工作
(1)基本构成:
[ 函数对象参数 ](操作符重载函数参数)mutable -> 返回值 { 函数体 }
注意
[],标识一个Lambda的开始,这部分必须存在,不能省略
例子:
注意:
最后加个括号,表示 “调用”,而不是 “声明“
例子:
总结:
函数对象参数有以下形式:(一般使用 ”=“ 就足够了,其他都很少用)
(1)空。没有使用任何函数对象参数。
(2)=====。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是***值传递方式***(相当于编译器自动为我们按值传递了所有局部变量)。
(3) &。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是***引用传递方式***(相当于编译器自动为我们按引用传递了所有局部变量)。
(4) this。函数体内可以使用Lambda所在类中的成员变量。
(5)a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。
mutable关键字:
例子:
一个信号可以连接多个槽函数(使用lambda表达式的优势,比较方便):
QMainWindow是一个为用户提供主窗口程序的类,包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个锚接部件(/浮动窗口)(dock widgets)、一个状态栏(status bar)及一个中心部件(central widget),是许多应用程序的基础,如文本编辑器,图片编辑器等
菜单栏meanBar()不用设置this,因为它是系统默认的,所以同时它也不用new(区别于工具栏)
只能有一个,所以是setMenuBar(bar),只能set一次
工具栏QToolBar(this) 需要设置this,同时也要new
补充:
工具栏可以有多个,所以是addToolBar( … ),可以add多个
状态栏statusBar()不用设置this,因为它是系统默认的,所以同时它也不用new(区别于工具栏)
只能有一个,所以是setStatusBar(stBar),只能set一次
标签控件:
需要new(类似 ”按钮控件“),也需要设置parent,(this)
需要new,需要设置parent,(this)。因为它是部件(控件)
铆接部件可以有多个,所以是addDockWidget( … ),可以add多个
只能有一个,所以是seCentralWidget(edit),只能set一次
注:使用相对路径
1.1 将图片文件 拷贝到项目位置下
1.2 右键项目->添加新文件 –> Qt - > Qt recourse File - >给资源文件起名
1.3 res 生成 res.qrc
1.4 open in editor 编辑资源
1.5 添加前缀 添加文件
1.6 使用 “ : + 前缀名 + 文件名”
对话框通常会是一个顶层窗口,出现在程序最上层,用于实现短期任务或者简洁的用户交互
Qt 中使用QDialog类实现对话框。就像主窗口一样,我们通常会设计一个类继承QDialog
顶层窗口:在任务栏会有自己的位置;
非顶层窗口:则会共享其父组件的位置
下面的演示例子用到了lambda表达式
不可以对其他窗口进行操作(阻塞同一应用程序中其它窗口的输入)
使用QDialog::exec()
实现 应用程序级别 的模态对话框
使用QDialog::open()
实现 窗口级别 的模态对话框
窗口级别的模态依然允许用户与程序中其它窗口交互,窗口级别的模态尤其适用于多窗口模式
一般默认是 ” 应用程序级别的模态 “
例子:
exec()相当于阻塞
可以对其他窗口进行操作
QDialog::show()
实现 非模态对话框例子:
注:
QDialog dialog(this)
的方式,dialog是建立在栈上的(立刻消失)
QDialog *dialog=new QDialog;
的方式,dialog是建立在堆上的(不会立刻消失),防止一闪而过
例子:
dlg2->setAttribute(Qt::WA_DeleteOnClose);
//55号 属性 //避免内存泄漏
//消息对话框
//错误对话框
QMessageBox::critical(this,"critical","错误");
//信息对话框
QMessageBox::information(this,"info","信息");
//提问对话框
//参数1 父亲 参数2 标题 参数3 提示内容 参数4 按键类型 参数5 默认关联回车按键
//QMessageBox::question 返回的类型是StandardButton,也是一个按键
if (QMessageBox::Save == QMessageBox::question(this,"ques","提问",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel))
{
qDebug() << "选择的是保存";
}
else
{
qDebug() << "选择的是取消";
}
//警告对话框
QMessageBox::warning(this,"warning","警告");
1.1 标准对话框 – 消息对话框
1.1.1 QMessageBox 静态成员函数 创建对话框
1.1.2 错误、信息、提问、警告
1.1.3 参数1 父亲 参数2 标题 参数3 显示内容 参数4 按键类型 参数5 默认关联回车按键
1.1.4 返回值 也是StandardButton类型,利用返回值判断用户的输入
返回值QColor
//颜色对话框
//QColor color = QColorDialog::getColor();//无参,默认(255,255,255)
QColor color = QColorDialog::getColor(QColor(255,0,0));
qDebug() << "r = " << color.red() << " g = " << color.green() << " b = " << color.blue() ;//打印R,G,B的值
QFileDialog::getOpenFileName(父亲,标题,默认路径,过滤文件)
返回值QString
//文件对话框 参数 1 父亲 参数2 标题 参数3 默认打开路径 参数4 过滤文件格式
//返回值是 选取的路径
QString str = QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\w1396\\Desktop","(*.txt)");
qDebug() << str;
返回值QFont
//字体对话框
bool flag;
QFont font = QFontDialog::getFont(&flag,QFont("华文彩云",36));
qDebug() << "字体:" << font.family().toUtf8().data() << " 字号 "<< font.pointSize() << " 是否加粗"<< font.bold() << " 是否倾斜"<<font.italic();
1.1 实现登陆窗口
1.2 利用布局方式 给窗口进行美化
1.3 选取 widget 进行布局 ,水平布局、垂直布局、栅格布局
1.4 给用户名、密码、登陆、退出按钮进行布局
1.5 默认窗口和控件之间 有9间隙,可以调整 layoutLeftMargin
1.6 利用弹簧进行布局
常用的按钮:
QPushButton
常用按钮
QToolButton
工具按钮 用于显示图片;如图想显示文字,修改风格:toolButtonStyle,改成ToolButtonTextBesideIcon;
凸起风格autoRaise(透明状态)
radioButton
单选按钮,设置默认 ui->rBtnMan->setChecked(true);
checkbox
多选按钮,监听状态,2 选中 1 半选 0 未选中
例子:
(1)界面:
(2)代码:
//利用listWidget写诗
// QListWidgetItem * item = new QListWidgetItem("锄禾日当午");
//将一行诗放入到listWidget控件中
// ui->listWidget->addItem(item);
// item->setTextAlignment(Qt::AlignHCenter);//水平居中
//QStringList QList
QStringList list ;
//左移拼接
list << "锄禾日当午" << "旱地和下土" << "谁知盘中餐"<< "粒粒皆辛苦";
ui->listWidget->addItems(list);
总结:
1.1.1 QListWidgetItem * item 一行内容
1.1.2 ui->listWidget ->addItem ( item )
1.1.3 设置居中方式item->setTextAlignment(Qt::AlignHCenter);
1.1.4 可以利用addItems一次性添加整个诗内容
treeWidget树控件使用
//设置水平头
ui->treeWidget->setHeaderLabels(QStringList()<< "英雄"<< "英雄介绍");
QTreeWidgetItem * liItem = new QTreeWidgetItem(QStringList()<< "力量");
QTreeWidgetItem * minItem = new QTreeWidgetItem(QStringList()<< "敏捷");
QTreeWidgetItem * zhiItem = new QTreeWidgetItem(QStringList()<< "智力");
//加载顶层的节点
ui->treeWidget->addTopLevelItem(liItem);
ui->treeWidget->addTopLevelItem(minItem);
ui->treeWidget->addTopLevelItem(zhiItem);
//追加子节点
QStringList heroL1;
heroL1 << "AAA" << "aaaaaaaaaaaaaaaaa";
QTreeWidgetItem * l1 = new QTreeWidgetItem(heroL1);
liItem->addChild(l1);
总结:
1.1.1.1 ui->treeWidget->setHeaderLabels(QStringList()<< "英雄"<< "英雄介绍");
1.1.2.1 QTreeWidgetItem * liItem = new QTreeWidgetItem(QStringList()<< "力量");
1.1.3.1 ui->treeWidget->addTopLevelItem(liItem);
liItem->addChild(l1);
利用QStringList()<<"…" 左移实现添加字符串到List列表
//TableWidget控件
//设置列数
ui->tableWidget->setColumnCount(3);
//设置水平表头
ui->tableWidget->setHorizontalHeaderLabels(QStringList()<<"姓名"<< "性别"<< "年龄");
//设置行数
ui->tableWidget->setRowCount(5);
//设置正文
//ui->tableWidget->setItem(0,0, new QTableWidgetItem("亚瑟")); //在这里new,创建匿名对象
QStringList nameList;
nameList<< "亚瑟"<< "赵云"<< "张飞"<< "关羽" << "花木兰";
QList<QString> sexList;
sexList << "男"<< "男"<< "男"<< "男"<< "女";
for(int i = 0 ; i < 5 ;i ++)
{
int col = 0;
ui->tableWidget->setItem(i,col++, new QTableWidgetItem(nameList[i]));
ui->tableWidget->setItem(i,col++, new QTableWidgetItem(sexList.at(i)));
//int 转 QString
ui->tableWidget->setItem(i,col++, new QTableWidgetItem( QString::number(i+18)));
}
ui->stackedWidget->setCurrentIndex(0);
ui->comboBox->addItem("奔驰");
ui->lbl_Image->setPixmap(QPixmap(":/Image/butterfly.png"))
ui->lbl_movie->setMovie(movie);
movie->start();
//栈控件使用
//设置默认定位 scrollArea
ui->stackedWidget->setCurrentIndex(0);
//scrollArea按钮
connect(ui->btn_scrollArea,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(1);
});
//toolBox按钮
connect(ui->btn_ToolBox,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(2);
});
//TabWidget按钮
connect(ui->btn_TabWidget,&QPushButton::clicked,[=](){
ui->stackedWidget->setCurrentIndex(0);
});
效果:
//下拉框
ui->comboBox->addItem("奔驰");
ui->comboBox->addItem("宝马");
ui->comboBox->addItem("拖拉机");
//点击按钮 选中拖拉机选项
connect(ui->btn_select,&QPushButton::clicked,[=](){
//ui->comboBox->setCurrentIndex(2);
ui->comboBox->setCurrentText("拖拉机");
});
效果:
//利用QLabel显示图片
ui->lbl_Image->setPixmap(QPixmap(":/Image/butterfly.png"));
//利用QLabel显示 gif动态图片
QMovie * movie = new QMovie(":/Image/mario.gif");
ui->lbl_movie->setMovie(movie);
//播放动图
movie->start();
效果:
创建一个QT设计师界面类(.h .c .ui ),然后在这个新生成的 .ui 文件 里面自定义控件
(自定义控件 需要加载到主窗口中才能生效)
(在主窗口 widget.ui 里面点击“提升为”,粘贴“自定义控件对应的类名”)
(注意类型一致才可以提升成功)
(实际显示的窗口大小根据 widget.ui 设置的 widget 的大小决定,而不是 “自定义控件.ui” 里面的大小决定)
设置 自定义控件之间的联系,就是设置A控件发出的信号被B控件捕获,然后处理
(1)两个控件关联:
部分代码:
smallwidget.cpp:
//QSpinBox移动,QSlider跟着移动
//因为发出信号者的函数有重载,所以要写成函数指针形式
void (QSpinBox::*spSignal)(int)=&QSpinBox::valueChanged;
connect(ui->spinBox,spSignal,ui->horizontalSlider,&QSlider::setValue);
//QSlider滑动 QSpinBox数字跟着改变
//这个发出信号者没有重载,所以不用写函数指针
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
效果:
(2)设置、获取(部分代码):
smallwidget.h:
void setnum(int num);//设置为50
int getnum();//获取当前值
smallwidget.cpp:
//设置为50
//记得设置作用域
void smallwidget::setnum(int num){
ui->spinBox->setValue(num);
}
//获取当前值
int smallwidget::getnum(){
return ui->spinBox->value();
widget.cpp 连接(信号和槽)(将按钮和自定义控件关联):
connect(ui->btn_set,&QPushButton::clicked,[=](){
ui->widget->setnum(50); //同时设置QSpinBox和QSlider为50
});
connect(ui->btn_get,&QPushButton::clicked,[=](){
qDebug()<<ui->widget->getnum();
});
效果:
总结:
1.1 鼠标事件
1.2 鼠标进入事件 enterEvent
1.3 鼠标离开事件 leaveEvent
1.4 鼠标按下 mousePressEvent ( QMouseEvent ev)
1.5 鼠标释放 mouseReleaseEvent
1.6 鼠标移动 mouseMoveEvent
1.7 ev->x()
x坐标 ev->y()
y坐标
1.8 ev->button()
可以判断所有按键 Qt::LeftButton Qt::RightButton
1.9 ev->buttons()判断组合按键 判断move时候的左右键 结合 & 操作符
1.10 格式化字符串 QString( “ %1 %2 ” ).arg( 111 ).arg(222)
1.11 设置鼠标追踪 setMouseTracking(true);
自定义控件 提升:类型一致才可以提升成功
自定义函数时注意加作用域
注意:
一定要将 ui 文件中的 Label 控件 从widget提升为QLabel,才能使鼠标事件与Label空间相关联。
mylabel.h:
#include
//记得这里改成public QLabel
class mylable : public QLabel
{
Q_OBJECT
public:
explicit mylable(QWidget *parent = nullptr);
//鼠标进入事件
void enterEvent(QEvent *event);
//鼠标离开事件
void leaveEvent(QEvent *);
//鼠标按下(virtual 不写也行)
virtual void mousePressEvent(QMouseEvent *ev);
//鼠标释放
virtual void mouseReleaseEvent(QMouseEvent *ev);
//鼠标移动
virtual void mouseMoveEvent(QMouseEvent *ev);
注:记得继承那里要改成public QLabel
mylabel.c:
#include
//记得这里改成QLabel(parent)
mylable::mylable(QWidget *parent) : QLabel(parent)
{
}
//鼠标进入事件
//记得设置作用域
void mylable::enterEvent(QEvent *event){
qDebug()<<"鼠标进入了";
}
//鼠标离开事件
void mylable::leaveEvent(QEvent *){
qDebug() << "鼠标离开了";
}
//鼠标按下(实现时 virtual 不写)
//mousePressEvent是系统类
void mylable::mousePressEvent(QMouseEvent *ev){
//当鼠标左键按下,提示信息
if(ev->button()==Qt::LeftButton){
QString str=QString("鼠标按下了 x=%1 , y=%2 ,global=%3 , global=%4 ").arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug()<<str;
}
}
//鼠标释放
//是系统类
void mylable::mouseReleaseEvent(QMouseEvent *ev){
if( ev->button() == Qt::LeftButton)
{
QString str = QString( "鼠标释放了 x = %1 y = %2 globalX = %3 globalY = %4 " ).arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug() << str;
}
}
//鼠标移动
//是系统类
void mylable::mouseMoveEvent(QMouseEvent *ev){
if( ev->buttons() & Qt::LeftButton )
{
QString str = QString( "鼠标移动了 x = %1 y = %2 globalX = %3 globalY = %4 " ).arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug() << str;
}
}
注:记得继承那里要改成QLabel(parent)
注:
因为有设置“提升为”,所以在自定义的类mylabel.c mylabel.h 里面设置就ok了,不用在去widget.c那里再设置信号和槽连接了。
(1)利用事件 void timerEvent ( QTimerEvent * ev)
(系统函数)
(2)启动定时器 startTimer( 1000)
毫秒单位
(3)timerEvent 的返回值是定时器的唯一标示 可以和 ev->timerId
做比较
widget.h
public:
explicit Widget(QWidget *parent = 0);
~Widget();
//重写定时器的事件
void timerEvent(QTimerEvent *);
int id1; //定时器1的唯一标示
int id2; //定时器2的唯一标示
widget.c
// #include //定时器类 在这个例子中用不到
#include
#include
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//第一种方式(不推荐)
//启动定时器 (注意:启动定时器与获取id写在构造函数)
id1 = startTimer(1000); //参数1 间隔 单位 毫秒
id2 = startTimer(2000);
}
//专门处理定时器的函数(系统函数)
void Widget::timerEvent(QTimerEvent * ev)
{
if(ev->timerId() == id1)
{
static int num = 1;
//label2 每隔1秒+1
ui->label_2->setText( QString::number(num++));
}
if(ev->timerId() == id2)
{
//label3 每隔2秒 +1
static int num2 = 1;
ui->label_3->setText( QString::number(num2++));
}
}
(1)利用定时器类 QTimer
(2)创建定时器对象 QTimer * timer = new QTimer(this)
(3)启动定时器 timer->start(毫秒)
(4)每隔一定毫秒,发送信号 timeout ,进行监听
(5)暂停 timer->stop
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include //定时器类 (用于创建定时器对象)
#include
#include
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//定时器第二种方式(使用 QTime 类)
QTimer * timer = new QTimer(this);
//启动定时器
timer->start(500);//500ms
connect(timer,&QTimer::timeout,[=](){
static int num = 1;
//label4 每隔0.5秒+1
ui->label_4->setText(QString::number(num++));
});
//点击暂停按钮 实现停止定时器
connect(ui->btn,&QPushButton::clicked,[=](){
timer->stop();
});
}
mylabel.h
//通过event事件分发器 拦截 鼠标按下事件
bool event(QEvent *e); //系统函数(但是也需要在 .h 文件声明,在.cpp中的实现相当于重写)
bool event(QEvent *e); //系统函数(但是也需要在 .h 文件声明,在.cpp中的实现相当于重写)
mylabel.cpp
bool myLabel::event(QEvent *e)
{
//如果是鼠标按下 ,在event事件分发中做拦截操作
if(e->type() == QEvent::MouseButtonPress)
{
QMouseEvent * ev = static_cast<QMouseEvent *>(e);
QString str = QString( "Event函数中::鼠标按下了 x = %1 y = %2 globalX = %3 globalY = %4 " ).arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug() << str;
return true; //true代表用户自己处理这个事件,不向下分发
}
//其他事件 交给父类处理 默认处理方式
return QLabel::event(e);//交给父类处理,mylabel的父类是QLabel
}
return QLabel::event(e);//交给父类处理,mylabel的父类是QLabel
(1)用途:用于事件的分发
(2)也可以做拦截操作,不建议
(3)bool event( QEvent * e);
(4)返回值 如果是true 代表用户处理这个事件,不向下分发了
(5)e->type() == 鼠标按下
…
(1) 在程序将时间分发到事件分发器前,可以利用过滤器做拦截
(2)步骤
给控件安装事件过滤器 (注意:在构造函数里面写)
重写 eventFilter
函数 (obj , ev)
widget.h
//重写事件过滤器的事件
bool eventFilter(QObject *, QEvent *);
widget.cpp
#include //需要包含这个头文件
#include
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//给label1 安装事件过滤器
// 步骤1 安装事件过滤器
ui->label->installEventFilter(this); //在构造函数中写
}
// 步骤2 重写 eventfilter事件
// 注意写作用域
//参数1:哪一个控件
//参数2:该控件的什么事件操作
bool Widget::eventFilter(QObject * obj , QEvent * e)
{
if(obj == ui->label)
{
if(e->type() == QEvent::MouseButtonPress)
{
QMouseEvent * ev = static_cast<QMouseEvent *>(e);
QString str = QString( "事件过滤器中::鼠标按下了 x = %1 y = %2 globalX = %3 globalY = %4 " ).arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
qDebug() << str;
return true; //true代表用户自己处理这个事件,不向下分发
}
}
//其他默认处理
return QWidget::eventFilter(obj,e);//交给父类处理,Widget的父类是Qwidget
}
return QWidget::eventFilter(obj,e);//交给父类处理,Widget的父类是Qwidget
(1)绘图事件 void paintEvent()
该函数是系统自动调用,如果没有重写该函数,系统则调用的该函数是空函数
(2)声明一个画家对象 QPainter painter(this)
this指定绘图设备(不是指绘图窗口)
(3)画线、画圆、画矩形、画文字
(4)设置画笔 QPen 设置画笔宽度 、风格
(5)设置画刷 QBrush 设置画刷 风格
1.1 抗锯齿 效率低
1.1.1 painter.setRenderHint(QPainter::Antialiasing);
1.2 对画家进行移动
1.2.1 painter.translate(100,0);
1.2.2 保存状态 save
1.2.3 还原状态 restore
1.3 如果想手动调用绘图事件 利用update()
1.4 利用画家画图片 painter.drawPixmap( x,y,QPixmap( 图片路径 ) )
1 QPaintDevice绘图设备
1.1 QPixmap 、 QImage、 QBitmap(黑白色) 、 QPicture、 QWidget
1.2 QPixmap 对不同平台做了显示的优化
1.2.1 QPixmap pix( 300,300)
1.2.2 pix.fill( 填充颜色 )
1.2.3 利用画家 往pix上画画 QPainter painter( & pix)
1.2.4 保存 pix.save( “路径”)
1.3 Qimage 可以对像素进行访问
1.3.1 使用和QPixmap差不多 QImage img(300,300,****QImage::Format_RGB32****);
1.3.2 其他流程和QPixmap一样
1.3.3 可以对像素进行修改 img.setPixel(i,j,value);
1.4 QPicture 记录和重现 绘图指令
1.4.1 QPicture pic
1.4.2 painter.begin(&pic);
1.4.3 保存 pic.save( 任意后缀名 )
1.4.4 重现 利用画家可以重现painter.drawPicture(0,0,pic);
1.3.1 file.open(打开方式)
QIODevice::readOnly
1.3.2 全部读取 file.readAll()
、按行读 file.readLine()
、 atend()判断是否读到文件尾
1.3.3 默认支持编码格式 utf-8
1.3.4 利用编码格式类 指定格式 QTextCodeC
1.3.5 QTextCodec * codec = QTextCodec::codecForName("gbk");
1.3.6 ui->textEdit->setText( codec->toUnicode(array) );
//gbk
1.3.7 文件对象关闭 close
1.4.1 file.open( QIODevice::writeOnly / Append)
1.4.2 file.write(内容)
1.4.3 file.close
关闭
1.1 QFileInfo info(路径)
1.2 qDebug() << “大小:” << info.size() << " 后缀名:" << info.suffix()<< " 文件名称:"< 1.3 1.4 widget.cpp 1、每一个场景写一个类(.c、.h) 2、实现方法相同的控件(系统自带控件/自定义控件)写在同一个类的不同方法(定义多个成员函数) 3、自定义控件的触发需要自定义一个信号发送出去、系统控件的触发不需要自定义信号 (注意:信号只需要声明,不需要实现) 4、一些操作写在构造函数里面,然后在创建那个对象的时候直接就把构造函数里面的语句执行了。 5、设置 bool 类型的属性的时候要给个默认值,否则有可能会出错。 6、设置不同界面切换位置一致 。 在 ”跳转“ 和 ”监听返回“ 两个地方都要设置。 7、项目打包,将qt左下角的…修改为Release模式,然后编译并运行,然后去到该项目文件夹将.exe文件复制粘贴到任意一个新的文件夹中,然后在该文件夹下打开命令行窗口,输入 如果想发布生成一个更美观的更完整的 ”应用程序“ ,可以使用第三方的工具进行发布。qDebug() << "创建日期:" << info.created().toString("yyyy/MM/dd hh:mm:ss");
qDebug() << "最后修改日期:"<
2、头文件
(1)#include < QFileDialog > 读取路径
(2)#include < QFile > 读取内容
(3)#include < QTextCodec > 编码格式
(4)#include< QFileInfo >
(5)#include< QDateTime >
3、代码
#include "widget.h"
#include "ui_widget.h"
#include
十七、开发注意事项
windeployqt 项目名称
然后回车,就可以看到刚刚创建的文件夹生成了很多配置文件之类的,将该文件夹发给其他人,其他人可以正常打开里面的.exe,运行项目。