快捷键:
选中多行---ctrl+/
ctrl+鼠标左键
右击一个函数
选择
注意:只有没有定义的函数Refactor才会有增加定义的选择,信号函数或者已经定义的函数没有增加定义的选项
自创建的类也会自动复合对象树:
tool-->options
connect(发送对象,信号,接收对象,槽函数),其中发送信号和槽函数需要用 SIGNAL() 和 SLOT() 来进行声明。
发送对象
就是发送信号的对象,比如按钮。
信号
就是特定的对象发送的事件,比如按钮发送的clicked(),本质上是一个函数。
接收对象
就是接受信号,并执行相应槽函数的对象,比如窗口。
槽函数
表示接受信号的对象是本窗口组件。
connect(ui->pushButton_todayPrice,&QPushButton::clicked,[=](){ui->stackedWidget->setCurrentIndex(0); });
利用lambda表达式实现槽函数
不需要接收对象,直接执行槽函数
右键转到槽
比如将PushButton转到槽函数,就是选择这个按钮作为发射信号的对象,选择好信号的类型之后就会为中国信号建立一个槽函数。
on+信号对象+信号类型(信号参数)
在UI界面进行的信号和槽的建立不需要自己去连接信号和槽,ui界面实现的功能都会在ui_x.h文件进行代码转换
connect(sender,signalType,receiver,signalDeal);
槽就是signalDeal----信号处理函数
sender----就是发送信号的按钮
connect(btn1,&QPushButton::clicked,this,&QPushButton::close);
注意第二和第四个参数
信号自定义:
槽函数自定义:
5.6以上版本都可以
先连接再触发信号,而不是先触发再连接:
定义不同类型的函数指针指向各个重载函数地址,无论是信号,还是槽函数,只要是有重载就要定义函数指针,利用函数指针关联起来信号和槽。
以函数指针作为信号函数和槽函数
不需要函数指针,即使用参数,直接发送信号的时候传参就可以
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);connect(ui->buttonOk,&QPushButton::clicked,this,&Widget::onBtnClicked);connect(this,&Widget::mysignal,this,&Widget::dealUserSignal);
}Widget::~Widget()
{delete ui;
}void Widget::onBtnClicked()
{QString str = ui->lineEdit->text();if(str.isEmpty())return ;emit mysignal(str); //发送信号
}void Widget::dealUserSignal(QString s)
{qDebug() << "offer = " << s;ui->labelOffer->setText(s);//正常我们按下取消键盘的时候,lineedit上的数据会被清除,那么我们来断开取消按钮和槽函数的链接disconnect(ui->buttonCancel,SIGNAL(clicked()),this,SLOT(on_buttonCancel_clicked()));
}//按下取消按钮的时候
void Widget::on_buttonCancel_clicked()
{ui->lineEdit->clear();
}
解决:
connect是按键和槽函数建立连接后保持连接
disconnect断开按键和槽函数的连接,让按键不能操作这个槽函数
要求无返回值
转到槽之后不需要连接
步骤
添加前缀的意义只是为了区分不同类型的资源文件。
注意:选择图片之后要进行保存(ctrl+s),只有保存,才会加入资源文件中,否则是没有添加成功的,成功会显示在Resources的下面。
resize(宽,高);
设置着窗口的大小
resize设置的窗口可以拖动改变大小
还可以设置固定的高,合作固定的宽,合作固定的高和宽
QPushButton
一定要定义为指针变量
按钮位置指定:move(距离左边x,距离上边y),不可以设置负数,否者就跑到左边的左边了,看不到
QString str = ui->lineEdit->text();
ui->lineEdit->setText(QString);
QMessegeBox::warning();
QMessegeBox::critical()
QMessageBox::information()
QMessageBox::qustion()
注意第一个参数是一个QWidget基类对象指针,一般设为nullptr
含有两个按键,怎么知道是按下了哪一个呢------通过返回值
//提示是否确认修改数据QMessageBox::StandardButton btn;btn=QMessageBox::question(nullptr,"提示","确定要修改数据吗",QMessageBox::Yes|QMessageBox::No);if(btn==QMessageBox::No)return;
//设置窗口固定大小setFixedSize(582,320);//去出窗口标题栏this->setWindowFlags(Qt::FramelessWindowHint);
选中窗口,搜索windowTitle属性修改就行。
setWindowTitle("first W");
两者都设置结果是代码设置的结果
选择choose resource...
刷新选择图片
注意:要使用这三个工具,要选择QMainWidget类,其他类没有这三个工具
QWidget:
menuBar()
返回菜单栏指针,如果不存在就创建再返回
c菜单栏的创建默认是放入窗口中的,所以不用传递this
上面的指针在局部定义也可以,因为作用域只是对变量限制,对开辟的内存不影响。
每一个都是一个指针
菜单栏,工具栏,状态栏的添加和删除都可以用代码来实现,但更方便的是直接在ui文件中添加和删除
直接双击菜单栏
一般添加图像,都是选择组件的xxxIcon属性
在菜单栏直接输入不了汉字,需要在行为编辑框中修改
转到槽
含有两个按键,怎么知道是按下了哪一个呢------通过返回值
显示指定目录或者文件下的所有文件和目录
仅显示指定文件
布完局,拖动窗口,里面的部件就可以变化了
以上两种图片添加的方式的区别
border-image:图片包含在整个框内
background-image:图片会消逝一部分
弹簧的使用原则------先布局再添加
方法
从小的布局到大的
对于有多页的组件,要点击每页页头进行布局
每一个布局框中的小组件布局之后都是对齐的,不要对子组件的部分进行布局,这样会导致对不齐
label不仅可以用来显示文字还可以用来显示静态图片和动态图片等
//图片的保存和显示QSqlQuery query(m_db);//获取房间图片,保存用来显示if(!query.exec("select roomPixma from ROOMPRICE")){QMessageBox::information(nullptr,"提示","没有插入图片");return;}query.first();m_pixByteArray=query.value(0).toByteArray();QPixmap outPixmap;outPixmap.loadFromData(m_pixByteArray);outPixmap=outPixmap.scaled(ui->label_picture->size());ui->label_picture->setPixmap(outPixmap);注意这两段代码:
outPixmap.loadFromData(m_pixByteArray);
outPixmap=outPixmap.scaled(ui->label_picture->size());
一定要先设置QPixmap对象的文件路径或者图片内容,再设置大小才有用。
直接ui设置,但是这种只能设置静态图
右键-----change style sheet
用者功能就可以直接差法按钮,而不需要再触发自己定义的信号和槽了,除非有需要。
直接转到槽就可以直接显示其他窗口。
布局之后再会出现红框,表示可以选择放入的位置
设置toolButton的文字和图片都可见
这种按钮一般和group box(组合框一起使用)
也可以直接双击修改
注意:不是setCheckable(bool)
按钮显示文本的修改
按钮编程使用名称的修改
先将所有按钮设置为一组
获取
QString permission=ui->buttonGroup_permission->checkedButton()->text();
for(int i=0;i<5;++i){for(int col=0;col<6;++col){ui->tableWidget_roomInfo->item(i,col)->setBackgroundColor(QColor(22, 169, 81));ui->tableWidget_roomInfo->item(i,col)->setForeground(Qt::red);}}
注意:单元格被设置的数量和位置一定要和开辟的第一个个数一样,否则;
来源------链接
出错代码
通过qtDesigner新建了一个QTableWidget对象,设置6行7列,然后我就通过如下方式进行item内容的设置for(uint8 i=0;i < ui->tableWidget->rowCount();i++)
{for(uint8 j=0; j < ui->tableWidget->columnCount();j++){ui->tableWidget->item(i,j)->setText(QString("%1 %2").arg(i).arg(j));}
}出现了segmentfault,内存段错误。原因分析
显然是出现了非法内存调用,查找发现,QTableWidget,表格与单元格是分开的,创建了表格(定义好了行列数)并不会相应创建单元格Item.
在使用时需要先实例化Item正确代码
需要在初始实例化阶段对Item进行实例化//初始化阶段
for(uint8 i=0;i < ui->tableWidget->rowCount();i++)
{for(uint8 j=0; j < ui->tableWidget->columnCount();j++){ui->tableWidget->setItem(i,j,new QTableWidgetItem("")); //实例化一个Item,显示内容为“”ui->tableWidget->item(i,j)->setTextAlignment(Qt::AlignCenter);//设置对齐方式}
}然后就可以正常使用了,只需要在初始化时实例化一次//使用阶段
for(uint8 i=0;i < ui->tableWidget->rowCount();i++)
{for(uint8 j=0; j < ui->tableWidget->columnCount();j++){ui->tableWidget->item(i,j)->setText(QString("%1 %2").arg(i).arg(j));}
}
也就是说要使用的第一个使用之前一定要先创建
换行符一定要在QString中才有用
for(int i=0;i<5;++i){for(int col=0;col<6;++col){ui->tableWidget_roomInfo->item(i,col)->setTextAlignment(Qt::AlignHCenter|Qt::AlignCenter);}}
//设置默认显示页ui->tabWidget->setCurrentIndex(0);
如果不设置视图为不可编辑
那么可以通过视图修改模型,从而修改数据库中的值
//设置模型提交方式为手动提交m_model->setEditStrategy(QSqlTableModel::OnManualSubmit);
设置为手动提交之后,利用按钮使用submitAll提交,看下面代码
没有提交之前才可以撤销
可以在不同的页设置不同的组件
注意“左右按键”只是为了设置时方便,不是切换的按钮,切换的按钮需要自己设置
1,右键点击右上角的小三角
2,有一个insert page
可以选择向前,向后插入页
条目的增加可以ui设计中直接设置,或者用函数设置
addItem()或者addItems()
QString roomNum=ui->comboBox_roomNum->currentText().remove(QRegExp("\\s"));
void SqlDataWidget::on_comboBox_manager_currentIndexChanged(int index){QSqlQuery query(m_db);//查询员工信息,然后填充到对应控件QString managerName=ui->comboBox_manager->currentText().remove(QRegExp("\\s"));//因为当删除所有员工进行再次填充时,下来控件也会检测到,所以当删除时,这个控件检测到就直接退出if(managerName.size()==0)return;QString str=QString("select UserName,password,sex,ID,birthdate,PhoneNum,address,email from ROOTINFO where UserName='%1'").arg(managerName);if(!query.exec(str)){QMessageBox::information(nullptr,"提示","没有查询到该员工信息");return;}
代码实现两者关联
1,复制小ui文件类名
2,在主Ui文件中添加从ui文件相同组件框
3,右键以上组件----promote(提升为)
基类要相同才可以提升
需要修改三个地方---三个基类的地方
被提升的组件也是一个个的对象,不要和在父类中定义同类型的对象混淆,自认为是同一个了。
提升的对象如同按钮可以使用
(ui->)
1,小部件建立自己的.cpp, .h, .ui文件,然后在主部件中提升
2,小部件建立自己的.cpp, .h,文件,在主部件中ui文件中画出,再提升
不同文件之间不需要包含,只需要在ui文件中提升进入,就可以通过这个用来提升的组件访问或者设置其他ui文件中的组件
要显示必须先建立对象,然后在合适的地方--.show()
无需调用,只需要声明和定义,会自动捕获鼠标事件
在哪个组件中定义的这两个函数,那么这两个组件就对这整个组件有作用
只能检测鼠标的进入和离开
鼠标事件也包含在QMouseEvent中
不一定是释放函数,主要是QMouseEvent参数
move如果不检测按键,鼠标移动他也可以追踪得到
构造函数中
调用repaint()或者update()
#include
#include
//创建QPixmap绘图设备(幕布)QPixmap pix(400,400);//设置幕布背景颜色pix.fill(Qt::blue);//建立画家QPainter painter(&pix);//设置画家画笔的颜色painter.setPen(QPen(Qt::red));//使用椭圆画圆painter.drawEllipse(QPoint(200,200),50,50);//pix.save(":\\image\\ellipse1.png");pix.save("D:\\QT\\QTlearn\\paintdevice\\image\\ellipse.png");//使用绝对路径
注意:以上两种绘图不会显示在输出窗口,因为我们指定画家的绘画窗口是我们自己定义的其他窗口,并且保存在文件中。
指定在输出窗口绘画
this->setStyleSheet();
标准QT库中qss的使用方法:
建立一个.qss文件,在.qss文件中设置样式
然后通过打开文件--->使用文件的方式设置样式
如果是指定大小,那最大最小值都要是同一个值才会变为设置的值
如果只设置最大值或者最小值,那么其大小就是最小最大值之间的值
当从数据库获取数据成功,触发信号,在父窗口中设置信号和槽的连接,只要信号触发,就显示主窗口、
进行样式设置时,不能同时设置背景图片和样式颜色,同时设置会导致样式无法看到。
按钮的背景颜色设置的时候看不到,运行之后才看得到
qt +=sql //加入之后先编译
#include
#include
#include
#include
#include
#include
QMessageBox::critical(nullptr,"error","linked failed"+m_db.lastError().text();
这一句要有---#include
//1query.prepare("update consumerInfo set stayState='已退房' where roomNum=?");query.bindValue(0,roomNum.toInt());if(!query.exec()){QMessageBox::critical(nullptr,"错误","客户入住信息没有修改成功");return;}//2QString strOutTime=QString("update consumerInfo set checkOutTime='%1' where roomNum=%2").arg(checkOutTime).arg(roomNum.toInt());if(!query.exec(strOutTime)){QMessageBox::critical(nullptr,"错误","客户退房时间没有修改成功");return;}
以上两种方式尽量使用第二种,第一种会莫名其妙地错误
数据库的open()函数返回bool类型的值
数据库使用完之后关闭
这个在析构函数中使用
//1
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("D:\\QT\\QTlearn\\studentsystem\\studentdatabase.db");if (!db.open())QMessageBox::warning(nullptr, "error","linked failed"+db.lastError().text());//2QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("studentdatabase.db");if (!db.open())QMessageBox::warning(nullptr, "error","linked failed"+db.lastError().text());
如果这函数指定的路径下有这个文件,就连接这个文件。
如果没有这个文件或者仅仅指定了这个文件,就在build......文件中建立这个文件,并连接这个数据库。
方法1:使用占位符---?
方法2: 使用:和字符
QSqlQuery query;query.prepare("INSERT INTO person (id, forename, surname) ""VALUES (:id, :forename, :surname)");query.bindValue(0, 1001);query.bindValue(1, "Bart");query.bindValue(2, "Simpson");query.exec();
只是判断查询语句知否执行成功
QSqlQuery query("SELECT * FROM artist");int fieldNo = query.record().indexOf("country");while (query.next()) {QString country = query.value(fieldNo).toString();doSomething(country);}
value的值可以是下标值,也可以是查询的字段名称
model----只负责存储数据
view------只负责显示数据
建立对象
前四步就可以获取并且显示数据
注意:这个模型和试图是对数据库的操作,所以要和数据库在同一个文件
QFile file("D:/QT/homework/SmartHotelProject/Code/hotelsystem/image/childRoom.jfif");if(!file.open(QIODevice::ReadOnly))return;else qDebug()<<"文件打开成功";QByteArray pixByteArray=file.readAll();QSqlQuery query(m_db);query.prepare("update ROOMPRICE set roomPixma=:pix where ID=2");query.bindValue(":pix",pixByteArray);if(!query.exec()){QMessageBox::information(nullptr,"提示","插入图片失败"+query.lastError().text());return;}elseqDebug()<<"插入成功";
而且使用绝对路径,未使用相对路径没有用
QString::number(int)
int num=100;
QString str;
str.setNum(num);
QString对象的函数toInt()
头文件---
#include
str=ui->spinBox_count->text();str.remove(QRegExp("\\s"));
在QT程序中,生成随机数比较简单。两个函数:
void qsrand(uint seed);
int qrand();
首先是初始化:qsrand()
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
接下来就可以生成随机数了:
int a = qrand();
qrand()理论上返回0 到 RAND_MAX间的值。
如果要返回0~n间的值,则为:qrand()%n;
如果要返回a~b间的值,则为:a + qrand() % (b - a)
不设置qsrand,qrand默认从1开始
1~35
for(int i=0;i<7;++i){vecn.append(qrand()%35);}
一、时间日期类型:
QTime:时间数据类型,表示时间,如:14:23:13。
QDate:日期数据类型,表示日期,如:2020-4-5。
QDateTime:日期时间数据类型,表示日期和时间,如:2020-03-23 08:12:43。
QDateTime:QDateTime dateTime= QDateTime::currentDateTime();//获取系统当前的时间QString str = dateTime .toString("yyyy-MM-dd hh:mm:ss");//格式化时间
复制
QString转化为QDateTime:QString str= "2020-11-02 12:24:36";
QDateTime time = QDateTime::fromString(str, "yyyy-MM-dd hh:mm:ss");
复制
字符串转换为 QTime、QDate 、 QDateTime 类型,使用静态函数 QDateTime::fromString(),其函数原型为: QDateTime QDateTime::fromString(const QString &string, const QString &format)
第 1 个参数 string 是日期时间字符串形式,第 2 个参数 format 是字符串表示的格式当前时间转化为时间戳:
QDateTime time= QDateTime::currentDateTime();//获取系统当前的时间
uint nTime = time.toTime_t();
复制
时间戳转化为当前时间://这个方法是静态的
QDateTime time = QDateTime::fromTime_t(timeT);
复制
二、 qt中用于时间、日期编辑和显示的界面组件
QTimeEdit:编辑和显示时间的组件。
QDateEdit:编辑和显示日期的组件。
QDateTimeEdit:编辑和显示日期时间的组件。
QCalendarWidget:用日历形式选择日期的组件。//获取当前日期时间,设置日期时间数据,并转换为字符串QDateTime curDateTime=QDateTime::currentDateTime();ui->timeEdit->setTime(curDateTime.time());ui->editTime->setText (curDateTime.toString ("hh:mm:ss));ui->dateEdit->setDate(curDateTime.date());ui->editDate->setText(curDateTime.toString("yyyy-MM-dd"));ui->dateTimeEdit->setDateTime(curDateTime);ui->editDateTime->setText(curDateTime.toString("yyyy-MM-dd hh:mm:ss"))
复制
QDateEdit 和 QTimeEdit 都是从 QDateTimeEdit 继承的,实现日期或时间的特定显示功能。实际上,QDateEdit 和 QTimeEdit 的显示功能都可以通过 QDateTimeEdit 实现,只需设置属性即可。
ui->dateEdit_m_birthDate->setDate(QDate::fromString(query.value(4).toString()));
//移除空字符后得到账号和密码
QString username=ui->usernameTextLineEdit->text().remove(QChar('\040'),
Qt::CaseInsensitive);
QString password = ui->passwordTextLineEdit->text().remove(QChar('\040'),
Qt::CaseInsensitive);
1,setText的参数必须是字符串才可以写入
比如:QT += sql
加入之后要先编译,才有效果。