QT的学习笔记5——自定义控件、鼠标事件、定时器、绘图、QFile文件操作等

📅 2026/7/14 19:14:55
QT的学习笔记5——自定义控件、鼠标事件、定时器、绘图、QFile文件操作等
1、自定义控件封装首先新建一个项目之后右键项目选择Add new选择新建一个设计师界面类包含头文件、cpp文件和ui界面之后在新建的Ui界面中分别添加以下两个控件将控件在ui中摆成以下形状并将整体布局变小之后在项目的widget.ui中选择一个widget控件放到界面中之后右键选择提升为选择新加的文件的头文件中的类名选择添加并勾选全局包含上方会出现以上内容之后勾选提升右上角会出现相应的类型最后运行程序可得以上组合控件此外由于勾选了全局包含因此下一次再次添加widget控件之后右键选择提升为此时这个组合控件已经存在可直接勾选即可之后为实现滑动或者加减控件另一个控件也在变化在small(自定义控件)对应的cpp中添加以下代码void(QSpinBox::*spin)(int)QSpinBox::valueChanged;//信号发生重载需要重定义一下connect(ui-spinBox,spin,ui-Slider,QSlider::setValue);//连接当spinbox发生变化时slider会发生改变connect(ui-Slider,QSlider::valueChanged,ui-spinBox,QSpinBox::setValue);//当slider发生变化时spinbox会发生改变以上的信号和槽函数可以在帮助文档中在控件前加一个Q即可查到对应的信号和槽函数如果没有则可以去查找他们的父类通过父类去找到对应的信号或槽函数之后为了实现其余功能这里新增两个按钮一个是获取当前值、一个是设置值为一半首先需要在主ui界面中添加两个按钮之后分别对两个按钮的名称进行改写也可以不改但不改之后使用按钮名称并不是那么简洁在small.h文件中的public下对两个功能进行编写//设置值 void setNum(int num); //获取值 int getNum();并在对应的cpp中实现相应操作//设置值 void small::setNum(int num){ ui-spinBox-setValue(num); } //获取值 int small::getNum(){ return ui-spinBox-value(); }最后在主页面的cpp中添加两个接口的连接使用qDebug记得在cpp那里声明//获取控件当前的值 connect(ui-get_value,QPushButton::clicked,[](){ qDebug()ui-widget-getNum(); }); //设置控件的值 connect(ui-half_value,QPushButton::clicked,[](){ ui-widget-setNum(50); });运行之后结果如下首先随意拉动到某一值打印结果正确之后点击设置到一半功能成功实现2、QT中的鼠标事件首先新建一个项目之后右键选择add new由于这次不是添加一个控件因此可以选择添加c:命名为mylabel并选择QWidget文件类型为QWidget在新项目的ui中添加一个label之后选中右键选择提升为将新添加的类名添加到提升的类名称处之后选择添加添加之后选择提升之后在mylabel的头文件的public中添加以下内容//鼠标进入事件 void enterEvent(QEvent *event); //鼠标离开事件 void leaveEvent(QEvent *event);在相应的cpp文件中直接在已有代码下添加以下内容//鼠标进入事件 void mylabel::enterEvent(QEvent *event){ qDebug()鼠标移入; } //鼠标离开事件 void mylabel::leaveEvent(QEvent *event){ qDebug()鼠标移出; }为了防止ui界面的label看不到可以在这里修改外边框最后运行代码即可将鼠标放到框内打印“鼠标移入”移出之后显示“鼠标移出”之后在mylabel.h中添加以下代码//鼠标移动事件 void mouseMoveEvent(QMouseEvent *ev); //鼠标按下事件 void mousePressEvent(QMouseEvent *ev); //鼠标释放事件 void mouseReleaseEvent(QMouseEvent *ev);对应cpp//鼠标移动事件 void mylabel::mouseMoveEvent(QMouseEvent *ev){ qDebug()鼠标移动了; } //鼠标按下事件 void mylabel::mousePressEvent(QMouseEvent *ev){ qDebug()鼠标按下了; } //鼠标释放事件 void mylabel::mouseReleaseEvent(QMouseEvent *ev){ qDebug()鼠标释放了; }之后运行代码目前移动只有在按下鼠标时才会显示为了可以在按下的时候显示x、y需要用到参数ev首先在cpp的头部添加#includeQMouseEvent之后将按下中的代码进行更改QString strQString(鼠标按下了 x%1 y%2 globalx%3 globaly%4).arg(ev-x()).arg(ev-y()).arg(ev-globalX()).arg(ev-globalY()); qDebug()str;其中x、y表示鼠标在框内的坐标globalx和globaly表示在整个大屏幕的坐标之后实现只有鼠标左键按下时才显示按下的代码上述是button已定义好的按键类型之后对按下的代码进行改写//只有按下左键才打印 void mylabel::mousePressEvent(QMouseEvent *ev){ if(ev-button()Qt::LeftButton){ QString strQString(鼠标按下了 x%1 y%2 globalx%3 globaly%4).arg(ev-x()).arg(ev-y()).arg(ev-globalX()).arg(ev-globalY()); qDebug()str; } }之后运行代码按下右键不显示只有按下左键才会显示对于移动按钮来说由于它在移动过程中状态是运动的因此不能用上面的方式判断是否是左键按下这里采用buttons和只有当每次按下的键都是左键才执行/鼠标移动事件 void mylabel::mouseMoveEvent(QMouseEvent *ev){ if(ev-buttons() Qt::LeftButton){ QString strQString(鼠标移动到 x%1 y%2 globalx%3 globaly%4).arg(ev-x()).arg(ev-y()).arg(ev-globalX()).arg(ev-globalY()); qDebug()str; } }结果如下所示如果只想显示移动的功能可以使用鼠标追踪首先将刚刚按下是否为左键的代码注释之后在函数中添加代码开启追踪即可此时不用按下左键移动时就会显示3、定时器第一种方式可以在ui界面中添加两个框一个放1s定时、一个放2s定时界面如下在widget.h中的public声明函数名和变量void timerEvent(QTimerEvent * ev);//重写定时器事件 int id1;//定时器名称 int id2;之后在cpp文件中实现Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui-setupUi(this); //启动定时器,1s运行一次 id1startTimer(1000); //启动定时器2s运行一次 id2startTimer(2000); } void Widget::timerEvent(QTimerEvent * ev){ if(ev-timerId()id1){//如果是第一个定时器就执行以下代码 static int num11;//使用静态变量使得运行后num可以变化 ui-label_2-setText(QString::number(num1)); } if(ev-timerId()id2){ static int num21; ui-label_3-setText(QString::number(num2)); } }实现效果上面的定时器是1s一变下面是2s一变第二种方式使用类进行创建对象更推荐首先在ui界面在添加一个label之后在widget.cpp的开头添加QTimer的头文件之后在widget的函数中直接添加代码即可QTimer *timernew QTimer(this); timer-start(500);//0.5s运行一次 connect(timer,QTimer::timeout,[](){ static int num31;//使用静态变量使得运行后num可以变化 ui-label_4-setText(QString::number(num3)); });结果如下给定时器添加一个暂停按钮功能按下按钮之后当前定时器停止计时在Ui界面添加一个按钮之后在cpp文件中再添加一个连接//按下暂停按钮定时器停止 connect(ui-pushButton,QPushButton::clicked,[](){ timer-stop(); });运行结果如下4、event事件分发器当event对鼠标按下事件进行处理不向下分发时这个事件将只会由event处理而不会再让mousePressEvent进行处理事件过滤器5、绘图使用QT在widget中绘图首先新建一个项目之后在widget.h的public中新增一行绘图函数的代码//绘图事件void paintEvent(QPaintEvent *) ;之后在对应的cpp文件中先声明头文件#includeQPainter//画家类之后对绘图函数进行编写void Widget::paintEvent(QPaintEvent *){ //实例化一个画家对象this表示指定绘图设备 QPainter painter(this); painter.drawLine(QPoint(0,0),QPoint(100,100)); }结果如下生成一条从00到100100的直线painter.drawEllipse(QPoint(100,100),50,50);//画圆圆心rxrypainter.drawRect(QRect(20,20,50,50));//画矩形前两个参数是矩形的顶点坐标之后是宽最后是高painter.drawText(QRect(10,200,100,50),好好学习天天向上);//画文字前面的QRect相当于一个文本框的顶点宽高后边是添加的文字为了保证字都显示在同一行可以调整宽的数字painter.drawText(QRect(10,200,150,50),好好学习天天向上);还可以设置画笔的颜色QPen pen(QColor(255,0,0));//画笔的颜色 painter.setPen(pen);//设置画笔在那里设置在那里之后的形状颜色都会发生改变pen.setWidth(3);//设置画笔宽度字体效果不变图形的变宽了pen.setStyle(Qt::DotLine);//设置画笔风格,除字体QBrush brush(Qt::cyan); painter.setBrush(brush);//使用画刷填充图形2高级设置首先画两个相切的园QPainter painter(this); painter.drawEllipse(QPoint(100,100),50,50); painter.drawEllipse(QPoint(200,100),50,50);在第二个圆前添加一行代码 painter.setRenderHint(QPainter::Antialiasing);//抗锯齿能力减少圆的毛刺从图中可得右边的圆比左边的减少了一定的毛刺之后是原点平移的操作painter.drawRect(QRect(20,20,50,50));//画一个矩形 painter.translate(100,0);//画家平移了100的位置 painter.save();//保存画家现在的位置不保存依然还在这个新位置绘画 painter.drawRect(QRect(20,20,50,50)); painter.restore();//回到画家上一个位置 painter.drawRect(QRect(20,20,50,50));先画一个矩形→将原点平移1000的位置可保存也可不保存当前位置→再画一个矩形→返回到上一个原点位置→再画一个矩形之后添加一个按钮实现点击一次按钮形成的图片就可以移动一次首先在widget.cpp的绘图函数中添加几行代码QPainter painter(this);//新建一个画家 pox10;//每点进这个函数一次其横坐标就加20 painter.drawPixmap(pox,50,QPixmap(:/pic/image/4.png));//画图片之后在widget.h的piblic中声明poxint pox0;//图片的初始x值最后在widget.cpp的构造函数中添加按钮的连接代码connect(ui-pushButton,QPushButton::clicked,[](){ update();//每按一次就可以更新一次绘画的函数 });结果如下每点击一次移动图片就会平移之后继续在绘图函数中添加if(poxthis-width()){//如果照片的最后一条边超出屏幕大小则从0开始 pox0; }保证当图片超出屏幕时就重新回到0开始可以对图片的像素点进行修改使用二维矩阵5、文件读取操作 QFile首先在Ui界面设置其中重要用了以下几个控件将pushbotton和line edit放在同一个widget中并使用水平布局之后将text edit拖入之后点击最大的widget选择垂直布局即可将以下代码添加到widget.cpp的构造函数中connect(ui-pushButton,QPushButton::clicked,[](){ QString pathQFileDialog::getOpenFileName(this,打开文件,C:\\Users\\xzhao\\Desktop);//点击按钮弹出文件对话框 ui-lineEdit-setText(path);//将文件路径显示在lineEdit框内 //将该路径下的内容放到textEdit框内 QFile file(path); file.open(QIODevice::ReadOnly);//设置打开方式 QByteArray arrayfile.readAll();//读取当前路径下的所有内容 ui-textEdit-setText(array); file.close();//关闭文件 file.open(QIODevice::Append); //这个是继续在上述打开的文件后进行追加的写,运行之后自动添加到txt文件中先不会在框内显示打开txt文件后会显示已修改的文档 file.write(诶诶诶诶);//添加文字 file.close(); });结果如下选择文件之后进行了显示txt也有了一定的修改之后还可以在读取文件之后获取额外的信息首先在cpp头部添加两个库#includeQDebug #includeQDateTime//QFileInfo文件信息类 QFileInfo info(path); qDebug()大小info.size()后缀名info.suffix()文件名称info.fileName()文件路径info.filePath(); qDebug()创建日期info.created().toString(yyyy/MM/dd hh:MM:ss); qDebug()最新修改日期info.lastModified().toString(yyyy/MM/dd hh:MM:ss);之后在cpp的lambda表达式中继续添加上述代码结果如下