DAY01
添加按钮之前先包含头文件,在widget.h中#include<QPushButton> ,第一个字母都是Q。继续在private:下面添加如下代码。
private:
QPushButton b1;
QPushButton *b2;
b2 = new QPushButton("hello,qt");
b2->show();
界面如图所示,未达到预期效果,因为窗口2没有依附窗口1。  如果窗口需要依附另外一个窗口,需要给该窗口指定一个父类。让他依附于谁就把窗口类传给他。
b2 = new QPushButton("hello,qt",this);
用第一种方式创建按钮,没有用.show();也出现了 父窗口显示的时候,子窗口也会随之显示。如果有100个窗口还要show100次,但是指定了this这个父类,子类就不需要show了。但是出现了hello qt被覆盖了,于是我们要改变按钮的位置。得出结论,窗口的坐标系原点在左上角,X轴向右递增,Y轴向下递增。  QT中的对象树。析构顺序和构造的顺序相反。QT的内存回收机制:1、使用的类是直接或者间接从QObject的派生。2、类在创建对象的时候指定父对象,在析构的时候首先析构子类对象。 添加新文件不改变参数类型只改变父类对象。并且在头文件中添加析构函数。  析构过程:在widget.h中创建对象,之后运行项目。  运行结果如图所示。 关闭UI界面的时候,默认被释放。 
函数的使用
对于类来说,直接按下F1进入帮助文档,对于类的函数来说,指定完成参数之后按下F1进入帮助文档。   设置窗口的标题,在widget下用this指针指向本作用域。也可以在main函数中对窗口标题进行设置,直接用到w.resize(),w.setWindowTitle()函数。
this->setWindowTitle("环境监测系统");
设置固定的窗口大小。
this->setFixedSize(200,300);
设置窗口图标
this->setWindowIcon(QIcon("D:\\1.png"));
标准的信号和槽
点击一下b1按钮关闭对象。函数剖析: 信号和槽都是函数,1、信号只有函数声明没有函数定义。 2、槽函数需要声明也需要定义。只是个回调函数。
connect (&b1,&QPushButton::clicked,this,&Widget::close);
更换需求:当按下b1的时候b2的显示内容改变。 槽函数的特性: /*自定义槽函数 *1、槽函数在Qt5中可以任意成员函数,全局函数,静态函数 lambda表达式(隐式函数) *2、槽函数需要与信号对应(返回值和参数) *3、信号是没有返回值的,槽函数的返回值是:void *4、void mysig(int,double,qstring); * void mtslot(int double qstring); *5、槽函数的信号是为了接收信号传过来的数据。 *6、槽函数的参数是不能够大于信号的参数个数,可以少于信号的参数个数。 *7、槽函数可以重载。 */
功能实现:在widget中添加声明,之后再在widget.cpp中完成函数实现。
自定义信号
更换需求:仅仅显示一个界面。 重新添加一个subwidget.cpp和subwidget.h。在头文集中声明QpushButton,在CPP文件中实现。在主窗口中包含头文件。子窗口初始化代码:
Subwidget::Subwidget(QWidget *parent) : QWidget(parent)
{
b1 = new QPushButton("中腾",this);
b1->resize(100,100);
setWindowTitle("软件园窗口");
resize(400,600);
}
主窗口头文件包含代码:
QPushButton *b3;
Subwidget subW;
主窗口cpp文件包含代码:
b3 = new QPushButton("软件园",this);
b3->resize(150,150);
b3->move(200,200);
connect(b3,&QPushButton::clicked,this,&Widget::slotHindMe);
然后从中腾返回主窗口的实现。要发送一个信号回到主窗口。
Subwidget::Subwidget(QWidget *parent) : QWidget(parent)
{
b1 = new QPushButton("中腾",this);
b1->resize(100,100);
setWindowTitle("软件园窗口");
resize(400,600);
connect(b1,&QPushButton::clicked,this,&Subwidget::myslot);
}
void Subwidget::myslot()
{
emit sigSub();
}
在主窗口widget中实现:
connect(&subW,&Subwidget::sigSub,this,&Widget::slotShowMe);
void Widget::slotShowMe()
{
show();
subW.hide();
}
重载的信号槽
信号槽不仅仅能发送一个信号,可以发送多个信号,发送多个信号的时候要用到函数指针,对多个信号进行重载,其次,还要声明作用域。如果信号和槽发生重载,要定义函数指针显示定义。
void Subwidget::myslot()
{
emit sigSub();
emit sigSub(250,"你是250");
}
connect(b3,&QPushButton::clicked,this,&Widget::slotHindMe);
void (Subwidget::*MySigSub)()=&Subwidget::sigSub;
connect(&subW,MySigSub,this,&Widget::slotShowMe);
void (Subwidget::*MySigPlus)(int ,QString)=&Subwidget::sigSub;
connect(&subW,MySigPlus,this,&Widget::slotSubMag);
拓展:1、信号可以连接信号 2、一个信号可以连接多个槽函数 3、多个信号可以连接一个槽函数 4、槽函数可以使用lambda表达式
lambda表达式
[=](){}值传递的方式,可以使用到函数外的参数。[&](){}引用外部的地址。[this](){}可以使用当前类的成员变量。[a](){}值传递的方式,可以传递a的值,大括号只能使用a。 使用lambad表达式作为槽函数。
第一天的复习内容
1、创建QT程序
1、一个Qt程序的组成部分:应用程序类,窗口类 2、应用程序类的个数:有且只有一个,QApplication a; 3、如何查看对应的模块: 光标移动到类上,F1 qmake += 模块的名字
2、第一个Qt程序
1>在窗口中添加按钮 类名:QPushButton 设置按钮显示的内容:setText 移动按钮的位置:move 按钮设置父窗口:setParent 设置窗口的大小:resize(),resizeFixed() 2>Qt的坐标体系: 坐标原点:左上角 x轴延伸方向:向右 y轴延伸方向:向下 3>Qt的内存回收机制 满足什么条件不需要用户手动释放内存? 1.从QObject类直接或间接派生。 2.从直接或间接派生出的类,指定父对象。
3、信号和槽
1>.格式:connect(信号发出者对象(指针),&className::clicked,信号接收者对象(指针),&classB::slot); 2>.标准信号槽的使用: 3>.自定义槽函数: 1:返回值void 2:可以重载 3:需要和信号对应,个数<=信号的参数个数 4>.自定义信号 1:返回值void 2:可以重载 3:需要使用一个关键字声明:signals; 4:不需要函数定义 5>.单参数的信号(槽) 1:重载的时候:信号槽发生了重载,需要使用函数指针。 2:Qt4信号槽的使用 SIGNAL(信号的函数名()),SLOT(槽函数名(int,long)) connect 连接 重载过的信号和槽的解决方法。
6>.拓展: a.信号可以链接信号(参数的对应)。 b.一个信号可以链接多个槽函数 c.多个信号可以链接同一个槽函数 d.槽函数可以使用lambda表达式
4、QMainWindow
1>.菜单栏
2>.工具栏
3>.浮动窗口和核心部件
4>.状态栏
5、QDialog
1>.模态对话框
2>.非模态对话框
3>.标准对话框和文件对话框
Day_1 课程总结精炼
Me wo;
Beauty sweet;
Beauty sweet1;
1>. 我 看到 美女 之后 ,我直流口水
connect(&wo,&Me::seeBeauty,&wo,&Me::mouthWatering);
2>.我 调戏 美女 , 美女抽我
connect(&wo,&Me::molestBeauty,&sweet,&Beauty::beatSomebody);
3>.我给两个美女些情书,一个同意,一个拒绝
void (Beauty::*slotAnswer)()=&Beauty::answer;
connect(&wo,&Me::writeLoveLetter,&sweet,slotAnswer);
void (Beauty::*slotAnswer1)(QString)=&Beauty::answer;
connect(&wo,&Me::writeLoveLetter,&sweet,slotAnswer);
4>.我拜托小红把情书给她的双胞胎妹妹小紫,小紫说我只喜欢会Qt的程序猿
connect(&wo,&Me::weituoLetter,&sweet1,&Beauty::sendLetter);
connect(&sweet1,&Beauty::sendLetter,&sweet,&Beauty::slotAnswer1);
DAY_02
QMainWindow
介绍UI界面,创建UI界面之后,如下:无法改变英文名,点击text输入中文,改变名称。  
connect(ui->actionopen,&QAction::triggered,this,[=]()
{
QString name = QFileDialog::getOpenFileName(this,"打开文件","D:\\","Image(*.jpg *.png)");
qDebug() << name;
});
讲解了浮动窗口的应用,如何使用浮动窗口。设置状态为floating,默认状态为浮动。 下面勾选框设置允许停靠的位置。 
1、资源文件的添加
在项目文件上右击添加新文件,选择天机resource file 添加新文件。添加成功后右击,加入前缀和反斜杠。把资源文件夹复制到工程文件夹下面,之后添加资源图片。
在mainwindow.cpp中添加代码如下。
ui->actionSave_as->setIcon(QIcon(":/IMAGE/3.png"));
即可显示出资源图片:  如果项目比较大,可以添加不同的前缀来添加文件。
资源文件的更简单的使用方法:左侧选择中标签,之后在资源管理中找到icon,在normal中添加资源中的图片

2、对话框-QDialog
模态&非模态对话框 非模态对话框:打开之后可以其他界面进行其他操作。 模态对话框:打开之后不可以其他界面进行其他操作。
connect(ui->actionopen,&QAction::triggered,this,[=]()
{
QDialog log(this);
log.exec();
QString name = QFileDialog::getOpenFileName(this,"打开文件","D:\\","Image(*.jpg *.png)");
qDebug() << name;
});
connect(ui->actionsave,&QAction::triggered,this,[=]()
{
QDialog *log =new QDialog(this);
log->show();
log->setAttribute(Qt::WA_DeleteOnClose);
QString name = QFileDialog::getOpenFileName(this,"打开文件","D:\\","Image(*.jpg *.png)");
qDebug() << name;
});
3、QMessageBox
实现包含的头文件 #include 实现代码:
QMessageBox::about(this,"about","++++++");
实现现象:  四种消息提示符:  如果执行了OK之后会出现的界面情况,最后一个参数为默认按钮,添加成功之后的界面,按下回车,按钮会响应回车按键:
if(QMessageBox::Ok == QMessageBox::critical(this,"error","系统文件错误!!!",QMessageBox::Ok|QMessageBox::Cancel,QMessageBox::Cancel))
{
QDialog log(this);
log.exec();
}
4、颜色和字体对话框
所需要包含的头文件: #include #include 返回值是QColor 获得颜色对话框。之后打印出红绿蓝的颜色属性。
QColor color = QColorDialog::getColor();
qDebug()<<color.red()<<color.green()<<color.blue();
返回值是QFont 获得字体的对话框,之后打印出字体属性(斜体,字体大小,加粗);
bool ok;
QFont font = QFontDialog::getFont(&ok,QFont("华文彩云"),this,"我的字体设置");
if(ok)
{
qDebug()<<font.family()<<font.italic()<<font.pointSize()<<font.bold();
}
5、布局
在开始布局之前首先为每一组控件创建一个父窗口。设置完成之后,界面如图所示。  为窗口设定最大宽度、高度和最小宽度、高度,来让界面固定大小。  网格布局:让每行每列的对齐,可以显示当行多列,每一列的宽度是相等的。 美化完成之后,选中对话框可以设置最后的间距大小,可以设置和边界的最后距离。 布局的时候,就是布局套布局,一层层布局下去。
6、按钮控件
1–PushButton按钮。 首先拖拽一个Button按钮放在UI界面上,在.cpp文件中,按下F1进入帮助文档,查看帮助文档信息,查看父类,在点击Signals。查看可以使用的信号。

每个控件放置在界面内一定要布置布局。 信号操作使用的实例:
connect(ui->radioButton,&QAbstractButton::clicked,this,[=]()
{
QMessageBox::information(this,"打印正确","hhhh");
});
单选框和复选框:  复选框使用示例,打印出控件的状态:
connect(ui->checkBox,&QCheckBox::stateChanged,this,[=](int state)
{
qDebug()<<state;
});
7、控件介绍
在QListWidget:控件中添加图片和文字。
ui->listWidget->addItem("软件创业园");
ui->listWidget->addItem(new QListWidgetItem(QIcon("D:\\1.png"),"Lufft"));
效果如下图所示:  table widget的使用:
ui->tableWidget->setRowCount(5);
ui->tableWidget->setColumnCount(3);
QStringList list;
list<<"姓名"<<"性别"<<"年龄";
ui->tableWidget->setHorizontalHeaderLabels(list);
测试结果: 
滚动条区域:Scroll Area 
Tool Box: 就像QQ列表的使用一样,点击一次按钮,就打开一次列表界面,使用效果如下图所示:  
TabWidget:分开显示界面。 
栈窗口:Stacked Widget 结果如下图所示:通过按键按钮,然后切换不同的界面。与QTabWidget 的区别是:这个控件和按钮是独立的,而QTabWidget是有联系的。    序号是当前窗口的currentIndex:
connect(ui->musicBtn,&QPushButton::clicked,this,[=]()
{
ui->stackedWidget->setCurrentIndex(0);
});
connect(ui->otherBtn,&QPushButton::clicked,this,[=]()
{
ui->stackedWidget->setCurrentIndex(1);
});
connect(ui->movieBtn,&QPushButton::clicked,this,[=]()
{
ui->stackedWidget->setCurrentIndex(2);
});
Combobox: 下拉框选择123进入电影界面。 
connect(ui->comboBox,&QComboBox::currentTextChanged ,this,[=]()
{
ui->stackedWidget->setCurrentIndex(2);
});
Qlabel类
在Qt中,QPixmap代表的是一张图片。如何插入图片呢? 首先添加资源文件,在UI界面添加lable控件,之后添加代码:
ui->image->setPixmap(QPixmap(":/IMAGE/3.png"));
结果显示如下: 
为了显示动图:要在头文件添加 #include,之后添加如下代码:
QMovie* movie = new QMovie(":/IMAGE/4.gif");
ui->image->setMovie(movie);
movie->start();
显示动态小猫咪如下图所示: 
DAY_03
自定义控件:封装一个控件的时候,先对疯转搞的控件进行处理。 首先添加一个文件,在文件中创建一部分控件。紧接着在主窗口把主窗口提升为之前设置的子窗口,默认选择全局包含,这样在之后的创建过程中,其他控件也可以提升为之前的子控件。 
  在smallwidget中先对里面的控件进行处理,添加如下代码:
void(QSpinBox::*sigValueChange)(int) = &QSpinBox::valueChanged;
connect(ui->spinBox,sigValueChange,ui->horizontalSlider,&QSlider::setValue;
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
实现功能数字变化,滑块也变化。滑块变化,数字也变化。 
小技巧:在使用控件的时候,做错了,重新更改边框,在widget右击变形为。。。
事件
在项目中添加新的C++文件,在C++文件上继承Qlabel,之后重写被保护的虚函数,虚函数的查看,在Qlabel中按下F1。QLabel是从QWidget中派生的。 
 实际上这些事件都是回调函数,我们只需要对这些函数进行功能实现即可。
QString 字符串的拼接
QString str = QString("%3,%2,%1").arg(1).arg("123").arg('a');
拼接后的结果如图所示:  鼠标事件的代码:
#include "mylabel.h"
#include <QMouseEvent>
Mylabel::Mylabel(QWidget *parent) : QLabel(parent)
{
this->setMouseTracking(true);
}
void Mylabel::enterEvent(QEvent *)
{
setText("鼠标进入");
}
void Mylabel::leaveEvent(QEvent *)
{
setText("鼠标离开~");
}
void Mylabel::mousePressEvent(QMouseEvent *ev)
{
QString btn;
if(ev->button()==Qt::LeftButton)
{
btn = "LeftButton";
}
else if(ev->button()==Qt::RightButton)
{
btn = "RightButton";
}
else if(ev->button()==Qt::MidButton)
{
btn = "MidButton";
}
QString str = QString("MousePress[%3]:(%1,%2)").arg(ev->x()).arg(ev->y()).arg(btn);
setText(str);
}
void Mylabel::mouseReleaseEvent(QMouseEvent *ev)
{
QString btn;
if(ev->button()==Qt::LeftButton)
{
btn = "LeftButton";
}
else if(ev->button()==Qt::RightButton)
{
btn = "RightButton";
}
else if(ev->button()==Qt::MidButton)
{
btn = "MidButton";
}
QString str = QString("MouseRelease[%3]:(%1,%2)").arg(ev->x()).arg(ev->y()).arg(btn);
setText(str);
}
void Mylabel::mouseMoveEvent(QMouseEvent *ev)
{
QString btn;
if(ev->buttons()&Qt::LeftButton)
{
btn = "LeftButton";
}
else if(ev->buttons()&Qt::RightButton)
{
btn = "RightButton";
}
else if(ev->buttons()&Qt::MidButton)
{
btn = "MidButton";
}
QString str = QString("MousePress[%3]:(%1,%2)").arg(ev->x()).arg(ev->y()).arg(btn);
setText(str);
}
定时器
使用方法一: 首先包含timerevent 的头文件,其次在窗口的构造函数中启动定时器。id = startTimer(100);参数100代表100ms触发一次。添加代码如下 实现启动定时器。当num>=100的时候关闭定时器。
static int num = 0;
QString str = QString("%1:%2").arg("Time out").arg(num++);
if(num >= 100)
{
killTimer(id);
}

使用方法2: 首先包含头文件QTimer,在构造函数中创建一个对象,创建对象完成之后,mylabel构造函数中添加如下代码,启动定时器:
QTimer *timer = new QTimer(this);
timer->start(100);
connect(timer,&QTimer::timeout,this,[=]()
{
static int number=0;
QString str = QString("%1:%2").arg("Time out").arg(number++);
this->setText(str);
});

QPrinter
首先在widget.cpp中包含头文件“#include ”,如果我们想在当前窗口绘图的话,我们需要重载一个虚函数。
protected:
void paintEvent(QPaintEvent *event);
void Widget::paintEvent(QPaintEvent *)
{
QPainter p(this);
QPen pen;
pen.setColor(QColor(0,255,0));
pen.setWidth(10);
pen.setStyle(Qt::DotLine);
QBrush brush(QPixmap(":/IMAGE/3.png"));
p.setBrush(brush);
p.setPen(pen);
p.drawPixmap(0,0,QPixmap(":/IMAGE/3.png"));
p.drawLine(QPoint(100,100),QPoint(300,500));
p.drawEllipse(QPoint(200,100),100,50);
p.drawRect(400,200,200,200);
QFont font("华文彩云",48,75,true);
p.setFont(font);
p.drawText(100,400,"我是你哥哥");
}
强制刷新界面
首先定义变量x;在UI界面添加按键,添加按键之后,创建槽函数。
connect(ui->move,&QPushButton::clicked,this,[=]()
{
update();
});
再完成槽函数之后,在 void Widget::paintEvent(QPaintEvent *) 添加如下代码。
int width = this->width();
int height = this->height();
x+=5;
if(x>this->width())
{
x=20;
}
p.drawPixmap(x,100,QPixmap(":/IMAGE/1.png"));
单击按键移动可以实现图片一直向右移动,即使跑出界面,也可以再进入界面。 
绘图设备
在widget添加如下代码:
ui->setupUi(this);
QPixmap pix(300,300);
pix.fill(Qt::red);
QPainter p(&pix);
p.setPen(QPen(Qt::green,10));
p.drawRect(10,10,280,280);
p.drawEllipse(150,150,50,50);
pix.save("D:\\mypixmap.jpg");
QImage img(300,300,QImage::Format_RGB32);
img.fill(Qt::red);
p.begin(&img);
p.setPen(QPen(Qt::green,10));
p.drawRect(10,10,280,280);
p.drawEllipse(150,150,50,50);
p.end();
img.save("D:\\myimage.jpg");
QPicture pic;
p.begin(&pic);
p.setPen(QPen(Qt::green,10));
p.drawRect(10,10,280,280);
p.drawEllipse(150,150,50,50);
p.end();
pic.save("D:\\mypic.jpg");
显示picture
void Widget::paintEvent(QPaintEvent *event)
{
QPainter p(this);
QPicture pic;
pic.load("D:\\mypic.jpg");
p.drawPicture(100,100,pic);
}
实现画图功能

不规则窗口
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QMouseEvent>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
pix.load("D:\\3.png");
this->setWindowFlag(Qt::FramelessWindowHint);
this->setAttribute(Qt::WA_TranslucentBackground);
}
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter p(this);
p.drawPixmap(0,0,pix);
}
void Widget::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
{
pq = event->globalPos() - this->frameGeometry().topLeft();
}
else if(event->button() == Qt::RightButton)
{
this->close();
}
}
void Widget::mouseMoveEvent(QMouseEvent *e)
{
this->move(e->globalPos() - pq);
}
实现用鼠标移动图标功能,单击右键实现关闭图片功能。 
|