Qt 笔记

目录

前言

毕竟自己工作内容是Qt,所以,我怕难免有可能被问到Qt的相关知识,所以,这部分,我也是要做好准备。

经验

  1. 一个控件从0到基本可用,如果差3条街的话,从可用到好用,还差着30条街。控件如此,软件系统亦如此。

  2. 有一种生意最赚钱,那就是教别人如何赚钱,让别人赚钱。有一种成功最成功,那就是让别人成功从而让自己获得成功!

  3. 在编程这条技术路线过程中,除了要耐得住寂寞,扛得住诱惑,技术深扎根以外,更需要自我总结、自我推动、自我激发、自我生产、自我疗伤、自我成长。学会左手温暖右手!

  4. 定时器是个好东西,学会好使用它,有时候用QTimer::singleShot可以解决意想不到的问题。

  5. 巧妙的使用findChildren可以查找该控件下的所有子控件。findChild为查找单个。

  6. Qtcreator软件的配置文件存放在:C:\Users\Administrator\AppData\Roaming\QtProject,有时候如果发现出问题了,将这个文件夹删除后打开creator自动重新生成即可。

  7. QList、QStringList、QByteArray强烈要求使用at而不是[]。因为at会进行数据检测。

  8. 如果是dialog窗体,需要在exec以后还能让其他代码继续执行,请在dialog窗体exec前增加一行代码,否则会阻塞窗体消息。
    QDialog dialog;
    dialog.setWindowModality(Qt::WindowModal);
    dialog.exec();

  9. 安全的删除Qt的对象类,强烈建议使用deleteLater而不是delete。因为deleteLater会选择在合适的时机进行释放,而delete会立即释放,很可能会出错崩溃。如果要批量删除对象集合,可以用qDeleteAll,比如 qDeleteAll(btns);

  10. 心中有坐标,万物皆painter,强烈建议在学习自定义控件绘制的时候,将qpainter.h头文件中的函数全部看一遍、试一遍、理解一遍,这里边包含了所有Qt内置的绘制的接口,对应的参数都试一遍,你会发现很多新大陆,会大大激发你的绘制的兴趣,犹如神笔马良一般,策马崩腾遨游代码绘制的世界。

  11. 在使用setItemWidget或者setCellWidget的过程中,有时候会发现设置的控件没有居中显示而是默认的左对齐,而且不会自动拉伸填充,对于追求完美的程序员来说,这个可不大好看,有个终极通用办法就是,将这个控件放到一个widget的布局中,然后将widget添加到item中,这样就完美解决了,而且这样可以组合多个控件产生复杂的控件。

  12. QVariant类型异常的强大,可以说是万能的类型,在进行配置文件的存储的时候,经常会用到QVariant的转换,QVariant默认自带了toString、toFloat等各种转换,但是还是不够,比如有时候需要从QVariant转到QColor,而却没有提供toColor的函数,这个时候就要用到万能办法。

if (variant.typeName() == "QColor") {
    QColor color = variant.value<QColor>();
    QFont font = variant.value<QFont>();
    QString nodeValue = color.name(QColor::HexArgb);
}
  1. Qt中的QString和const char *之间转换,最好用toStdString().c_str().

  2. Qt的信号槽机制非常牛逼,也是Qt的独特的核心功能之一,有时候我们在很多窗体中传递信号来实现更新或者处理,如果窗体层级比较多,比如窗体A的父类是窗体B,窗体B的父类是窗体C,窗体C有个子窗体D,如果窗体A一个信号要传递给窗体D,问题来了,必须先经过窗体B中转到窗体C再到窗体D才行,这样的话各种信号关联信号的connect会非常多而且管理起来比较乱,可以考虑增加一个全局的单例类AppEvent,公共的信号放这里,然后窗体A对应信号绑定到AppEvent,窗体D绑定AppEvent的信号到对应的槽函数即可,干净清爽整洁。

  3. 数据库处理一般建议在主线程,如果非要在其他线程,务必记得打开数据库也要在那个线程,即在那个线程使用数据库就在那个线程打开,不能打开数据库在主线程,执行sql在子线程,很可能出问题。

  4. 用QFile.readAll()读取QSS文件默认是ANSI格式,不支持UTF8,如果在QtCreator中打开qss文件来编辑保存,这样很可能导致qss加载以后没有效果。

  5. setPixmap是最糟糕的贴图方式,一般只用来简单的不是很频繁的贴图,频繁的建议painter绘制,默认双缓冲,在高级点用opengl绘制,利用GPU。

  6. 很多时候用QDialog的时候会发现阻塞了消息,而有的时候我们希望是后台的一些消息继续运行不要终止,此时需要做个设置。

QDialog dialog;
dialog.setWindowModality(Qt::WindowModal);
  1. 如果你没有使用wait***函数的话,大部分的界面卡都出在数据处理和展示中,比如传过来的是一张图片的数据,你需要将这些数据转成图片,这个肯定是耗时的;

  2. 多线程是需要占用系统资源的,理论上来说,如果线程数量超过了CPU的核心数量,其实多线程调度可能花费的时间更多,各位在使用过程中要权衡利弊;

  3. 在嵌入式linux上,如果设置了无边框窗体,而该窗体中又有文本框之类的,发现没法产生焦点进行输入,此时需要主动激活窗体才行。

//这种方式设置的无边框窗体在嵌入式设备上无法产生焦点
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);

//需要在show以后主动激活窗体
w->show();
w->activateWindow();
  1. QString的replace函数会改变原字符串,切记,他在返回替换后的新字符串的同时也会改变原字符串,我的乖乖!

  2. QObject类的定时器要设置的话调用 startTimer(interval, Qt::PreciseTimer);

  3. QLineEdit除了单纯的文本框以外,还可以做很多特殊的处理用途。
    限制输入只能输入IP地址。
    限制输入范围,强烈推荐使用 QRegExpValidator 正则表达式来处理。


//正在表达式限制输入
QString str = "\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b";
ui->lineEdit->setValidator(new QRegExpValidator(QRegExp(str)));
//用于占位
ui->lineEdit->setInputMask("000.000.000.000");

#if 0
//下面代码设置浮点数范围限制失败
ui->lineEdit->setValidator(new QDoubleValidator(20, 50, 1));
#else
//下面代码设置浮点数范围限制成功
QDoubleValidator *validator = new QDoubleValidator(20, 50, 1);
validator->setNotation(QDoubleValidator::StandardNotation);
ui->lineEdit->setValidator(validator);
#endif
//下面代码设置整数范围限制成功
ui->lineEdit->setValidator(new QIntValidator(10, 120));

//其实上面的代码缺陷很多,只能限制只输入小数,无法设定数值范围,很操蛋
//需要来个万能的牛逼的 QRegExpValidator

//限制浮点数输入范围为[-180,180]
QRegExp regexp("^-?(180|1?[0-7]?\\d(\\.\\d+)?)$");
//限制浮点数输入范围为[-90,90]并限定为小数位后4位
QRegExp regexp("^-?(90|[1-8]?\\d(\\.\\d{1,4})?)$");
QRegExpValidator *validator = new QRegExpValidator(regexp, this);
ui->lineEdit->setValidator(validator);

25.在继承自QAbstractItemView的控件中,比如QTableView、QTableWidget,如果文本超过队列item的宽度,则会自动省略号显示,想要快速显示完整的文本,可以在该列和下一列分割线中间双击即可,会自动自适应显示最大宽度,如果是Qt5.14或者更高版本,你会发现显示省略号的计算规则变了,如果是rtsp、http之类的开头的英文字符串,同样的列宽下,会提前就显示省略号,比如字符串 rtmp://58.200.131.2:1935/livetv/cctv1,会显示成 rtmp://… ,而在旧版本的Qt中会显示成 rtmp://58.200.131… ,很多时候我们并不想看到烦人的省略号,可以设置取消。

//取消自动换行tableView->setWordWrap(false);//超出文本不显示省略号tableView->setTextElideMode(Qt::ElideNone);
  1. 如果出现崩溃和段错误,80%都是因为要么越界,要么未初始化,死扣这两点,80%的问题解决了。
  2. 千万别在windows上面解压Linux的压缩包。
  3. 在拷贝文件到Linux的过程中,最好给所有文件赋新的权限。
    chmod +777 * -R

正文

1. 信号槽机制

1.1 定义

信号槽,实际上是一种观察者模式。当某个事件发生后,它就会发出一个信号。这种发出时没有目的性的,类似于广播。如果有对象对这个信号感兴趣的话,就会使用连接函数,将想要处理的信号和自己的一个槽函数连接起来。

1.2 多线程情况下, Qt中的信号槽分别在什么线程中执行, 如何控制?

通过 connect函数的第五个参数connectType来控制。

  1. Qt::AutoConnection:默认值,使用这个值则连接类型会在信号发送时自动确定。
  2. Qt::DirectionConnection:若接受者和发送者在同一个线程,则自动使用。槽函数会在信号发送的时候直接被调用,槽函数运行于信号发送者所在线程。效果看上去就像是直接在信号发送位置调用了槽函数。这个在多线程环境下比较危险,可能会造成奔溃。
  3. Qt::QueuedConnection:如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。
  4. Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。
  5. Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是避免了重复连接。

1.3 信号槽的优点和缺点

优点:

  1. 降低了Qt对象间的耦合度。

  2. 类型安全。信号的参数类型和参数个数必须同接收该信号的槽的参数类型和参数个数一致。

  3. 让代码的可读性和简洁成都上都相比回调函数要好一点。

缺点:

  1. 同回调函数相比,Qt的信号与槽比较慢,通过一个信号来调用槽函数将比直接调用非虚函数慢10倍。

2. Qt 智能指针学习

首先,为了管理资源,程序员通常采用RAII机制(Resource acquisition is inital)资源获取即初始化,在类的构造函数中申请资源,然后释放,最后在析构函数中释放资源。

如果没有智能指针,程序员必须保证new对象能在正确的时机delete,四处编写异常捕获代码以释放资源,而智能指针则可以在退出作用域时(不管是正常流程离开或是因异常离开)来调用delete来析构在堆上动态分配的对象。

2.1 智能指针所解决的问题:悬垂指针

悬挂指针其实就是两个指针指向同一块内存,但有一个指针被删除了,并且,其指向的内存也被释放了,就不能再去使用另一个指向这个内存的指针了。
如图,有两个指针a和b指向同一片内存,如果删除其中一个指针a,再去使用指针b的话,程序会崩溃。因为指针b此时已经是一个垂悬指针(Dangling pointer)了,它指向的内存已经被释放不再有效。
在这里插入图片描述
使用指针b之前先判断b是否为空,这个做法在这里是不起作用的。问题的本质是通过指针a去释放内存时,指针b没有同步地置为空。

假如指针b能随内存的释放而自动置为空就好了,这正是智能指针所要解决的问题。

2.2 智能指针

Qt提供了若干种智能指针:QPointer,QSharedPointer,QWeakPointer ,QScopedPointer, QScopedArrayPointer,QSharedDataPointer,QExplictlySharedPointer.

  1. QPointer
    QPointer只用于QObject的实例。如果它指向的对象被销毁,它将自动置空。
    在这里插入图片描述
  2. QSharedPointer & QWeakPointer

QSharedPointer是引用计数(强)指针,当所有强指针销毁时,实际对象才会销毁。
QWeakPointer是弱指针,可以持有对QSharedPointer的弱引用。它作为一个观察者,不会引起实际对象销毁,当对象销毁时会自动置空。
这两种指针同时都有以下3个成员:强引用计数strongRef,弱引用计数weakRef和数据data。
在这里插入图片描述
3. QScopedPointer
QScopedPointer保证当前范围指向的对象消失时将被删除。它拥有一个很好的名字,它向代码的阅读者传递了明确的信息:这个智能指针只能在本作用域里使用,不希望被转让,因为它的拷贝构造和赋值操作都是私有的。
4. 其他智能指针
QScopedArrayPointer:一个QcopedPointer,默认删除它指向Delete []运算符的对象。为方便起见,还提供了操作符[]。
QSharedDataPointer/QExplicitySharedDataPointer搭配QSharedData类一起使用,以实现自定义隐式共享或显式共享类。

3. 回调函数

所谓回调函数,就是通过函数指针调用的函数。如果把一个函数的指针作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方所调用的,而是在特定的事情或条件下由另外的一方调用的,用于对该事件或条件进行响应。

4. Qt对事件的响应是同步的还是异步的

应该是要根据connnect函数中的Connection_Type.并且,也要根据信号发出的线程与槽函数的线程是否是同一个线程来决定。
主要决定方法是:sender和receiver所处的线程,若是同一线程则同步,若是不同线程则异步。
Qt支持的六种连接方式:

  1. Qt::DirectConnection:直连方式。
    当信号发出后,相应的槽函数将立即被调用。emit语句后面的内容,将在所有的槽函数都执行完毕后被执行。
  2. Qt::QueueConnection:排队方式
    当信号发出后,排队到信号队列中,需等待接收对象所属线程的事件循环取得控制权时才取得该信号,调用相应的槽函数。emit后的语句将在发出信号后立即被执行,无需等待槽函数执行完毕。
  3. Qt::AutoConnection:自动方式
    Qt的默认连接方式,如果信号的发出和接收在这个信号的对象同属于一个线程,那么 其执行方式和直连相同。否则,就是排队方式。
  4. Qt:BlockingQueueConnection:阻塞队列方式

a. 信号和槽必须在不同的线程之中,否则就会造成死锁。
b. 槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。

  1. Qt::UniqueConnection
    与默认工作方式相同,只是不能重复连接相同的信号和槽(也就是connect函数不能重复执行多次),因为如果重复连接就会导致一个信号发出,对应槽函数就会执行多次。这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是避免了重复连接。

  2. Qt::AutoCompatConnection
    是为了连接Qt4与Qt3的信号槽机制兼容方式,工作方式与Qt::AutoConnection一样。

若参数没加的话,默认是直连方式。

参考1

5. Qt中信号和槽底层原理?

Qt信号槽的实现原理其实就是函数回调,不同的是直连直接回调、队列连接使用Qt的事件循环隔离了一次达到异步,最终还是使用函数回调。

  1. moc编译帮我们构建了信号槽回调的开头(信号函数体)和结尾,中间的回调过程Qt已经在QObject函数中实现。
  2. signals和slots就是为了方便Moc解析我们的C++文件,从中解析出信号和槽。
  3. 信号槽总共有5种连接方式,前四种是互斥的,可表示为同步或异步。
  4. 信号和槽本质上是一样的,但对于使用者来说,信号只需要声明,不需要实现,moc帮你实现,槽函数声明和实现都要自己写。
  5. connect函数就是把发送者,信号,接收者和槽储存起来,供后续执行信号查找。
  6. 信号触发就是一系列函数回调。

6. Qt隐式共享

浅拷贝
写时复制
在这里插入图片描述

7 Qt 元对象系统

什么是元对象系统?

Qt的元对象系统提供了a.对象间的通信机制(信号和槽),b.运行时类型信息和 c.动态属性系统的支持(Q_PROPERTY),是标准C++的一个扩展,它是Qt能够更好的实现GUI图形用户界面编程。

QObject类:作为每一个需要利用元对象系统的类的基类。也就是说只有继承QObject类才能使用MOS。
Q_OBJECT宏:定义在每一个类的私有数据段,用来启用元对象功能,比如,动态属性、信号和槽。

8.Qt: error: undefined reference to

  1. 解决方法是在display上面加了:
LIBS_LIST = on_driverCall  on_treeControl

9.QTreeWidget branch大小的调整

使用的不是啥Height,Width方式,而是:

m_pTreeWin = new CXmlTreeWidget();
m_pTreeWin->setProperty("class","m_pTreeWinQss");
m_pTreeWin->setIndentation(50);

10.条件编译||Qt在win上“启动程序失败,路径或者权限错误

 #ifdef UNIX_MINDVISION_GEV 
#endfi

这个条件编译的条件是取决是否有在文件中进行define UNIX_MINDVISION_GEV 的。

  1. 关于 Qt在win上“启动程序失败,路径或者权限错误"
    关于这个的原因,有可能是你的编译器选择错误了,有可能需要的是MSVC的,你的项目确实RK3399的。

11.在Qt5.12上安装opencv

看了巨多的帖子,都是写着要啥cmake啦!要替换啥文件啦,要怎么怎么,都是放狗屁喔!人家opencv的build里面是直接就可以用的。根本不用cmake的。
步骤如下

  1. 放置环境变量:
    D:\Study_Software\OpenCV\opencv\build\x64\vc15\bin
    还有这个:C:\Qt\Qt5.12.3\5.12.3\msvc2015_64\bin
    都放入系统环境变量Path之中。
  2. 在pro文件中加入这个东西:
INCLUDEPATH += D:/Study_Software/OpenCV/opencv/build/include
Debug:{
    LIBS += -lD:/Study_Software/OpenCV/opencv/build/x64/vc14/lib/opencv_world440d
}
Release:{
    LIBS += -lD:/Study_Software/OpenCV/opencv/build/x64/vc14/lib/opencv_world440
}

  1. 先对程序进行qmake一下。
  2. 文件头加入:#include <opencv2/opencv.hpp>
  3. 然后就编写程序就可以使用了:
#include "MainWindow.h"
#include "ui_MainWindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    cv::Mat src = cv::imread("C:/Users/19242/Pictures/01.jpg");
    cv::imshow("01.jpg",src);
}

MainWindow::~MainWindow()
{
    delete ui;
}

12.Qt小技巧

  1. 在这里插入图片描述

13.Qt的反射机制

1. 什么是反射机制?

是指在运行时,能获取任意一个类对象的所有类型信息、属性、成员函数等信息的一种机制。

2.使用Qt 反射机制的条件

  1. 需要继承自QObject类,并需要在类之中加入Q_OBJECT宏。
  2. 注册成员函数:若希望普通成员函数能够被反射,需要在函数声明之前加入
    QObject::Q_INVOKABLE 宏.
  3. 注册成员变量:若希望成员变量能被反射,需要使用Q_PROPERTY 宏.

14. 各种基本数据类型的转换

  1. std::string 转char* + String 转std::string
 std::string strValue = value.toStdString();
 CEnumFeaturePointer pEnumPoint = m_pFeature->GetEnumFeature(fName);
 pEnumPoint->SetValue((char*)strValue.c_str());

15.QObject: Cannot create children for a parent that is in a different thread.

在使用MoveToThread这种方式时,经常会遇到下面类似的问题:
QObject: Cannot create children for a parent that is in a different thread.
出现这个问题的原因: 我在子线程中使用了主线程创建的串口对象。从而导致上面的问题。

16. 多线程同时操作一个串口。

对于继承QThread重写run函数的情况,往往容易在run外部定义QSerialport *port = new QSerialport()对象,然后在run中调用port->readAll()等函数,然而根据QThread的特性,只有run函数才运行在新的子线程中,所以这里就跨线程调用了 QSerialport对象,会出现上述报错。

1.同一种操作(读 or 写)一定要放在同一个线程进行,否则线程间冲突整死人
2.QSerialPort对象的打开和关闭必须在对象的创建线程中执行,否则它的事件通知功能无法正常执行,结果便是waitForReadyRead或waitForBytesWritten这样的等待函数无法正常工作
参考1
QSerialPort适应多线程应用的改进
参考2

17. pro文件的注意事项

  1. constain(DEFINES,WIN_DVP_SHARE):含义是DEFINES下面是否有包含WIN_DVP_SHARE。所以在使用的时候,是有顺序的。要注意。
  2. constain(DEFINES,WIN_DVP_SHARE):含义是DEFINES下面是否有包含WIN_DVP_SHARE。所以在使用的时候,是有顺序的。要注意。

18. 如果为结构体内的指针申请空间?

结构体如下:

typedef struct _IMV_EnumEntryList
{
	unsigned int			nEnumEntryBufferSize;		///< \~chinese 存放枚举值内存大小					\~english The size of saving enumeration value 
	IMV_EnumEntryInfo*		pEnumEntryInfo;				///< \~chinese 存放可设枚举值列表(调用者分配缓存)	\~english Save the list of settable enumeration value(allocated cache by the caller)
}IMV_EnumEntryList;

typedef struct _IMV_EnumEntryInfo
{
	uint64_t				value;							///< \~chinese 枚举值				\~english  Enumeration value 
	char					name[IMV_MAX_STRING_LENTH];		///< \~chinese symbol名				\~english  Symbol name
}IMV_EnumEntryInfo;

申请内存空间的方式如下:

IMV_EnumEntryList pEnumEntryList;
IMV_EnumEntryInfo info;

pEnumEntryList.nEnumEntryBufferSize = sizeof(IMV_EnumEntryInfo) * pEntryNum;
pEnumEntryList.pEnumEntryInfo = (IMV_EnumEntryInfo*)malloc(sizeof(IMV_EnumEntryInfo) * pEntryNum);

19. char*[]数组的析构问题

问题:在申请了内存之后,没有在析构函数中进行析构,导致程序出现错误。
出问题的代码:

char*     m_pEnumList[1024];
for (int i = 0; i < MAX_PARAM_ELEMENT_NUMBER; i++)
{
     m_pEnumList[i] = new char[MAX_PATH];
}

未在析构函数函数中做出析构,于是在析构函数中增加了:

for (int i = 0; i < MAX_PARAM_ELEMENT_NUMBER; i++)
{
        delete [] m_pEnumList[i];
}

将char*数组中的每个元素都逐个析构。

20. 在QT生产库文件的过程中,未生成.lib文件以及.exp文件

解决方法:在需要引出的头文件的前面加上一个输出宏。# define ON_NETWORK_EXPORT Q_DECL_EXPORT。类似于加上ON_NETWORK_EXPORT ,这样,这个头文件中的include ,就可以被调用了。

21. 若在程序执行时未找到库的路径,则查找DEPENDPATH这个参数

22. 在发布版的程序中,也可以弹出提示框,打印调试信息

运行文件附带调试输出窗口,这个非常有用,很多时候当我们发布程序阶段,我们会遇到程序双击无法运行也不报错提示(开发机器上一切正常),都不知道发生了什么,甚至任务管理器可以看到运行了但是没有界面弹出来,此时就需要在项目的pro文件中加上一行CONFIG += console,带界面的程序也会自动弹出调试窗口打印输出信息,方便找问题,一般没法正常运行的程序都会打印一些提示信息缺啥之类的。

23. 若要让每个控件都有一个句柄

在MFC程序或者VB/C#等窗体程序中,每个控件都有一个句柄,而且用句柄工具移过去会自动识别,但是在Qt程序中默认Qt是一个窗体一个句柄,如果要让每个控件都拥有独立的句柄,在main函数中要做如下设置。

24. 20220222日常笔记

  1. Qt的线程创建完成后,应该在析构函数中去quit(),wait()掉这个线程。
    2.C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作。因此,被做为隐式类型转换使用。编译器在编译期处理,将地址a转换成类型T,T和a必须是指针、引用、算术类型或枚举类型。
    3.C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。
    4.dynamic_cast<T*>(a):表达式dynamic_cast<T*>(a) 将a值转换为类型为T的对象指针。如果类型T不是a的某个基类型,该操作将返回一个空指针。
  2. Qt中实现多线程就两种:一种是子类化QThread,重写run函数,在run函数中实现自己的代码,子类化QThread的方法,只有run函数里面的内容是执行在子线程里的,其他的部分,比如槽函数什么的还是在主线程里执行(假设是在主线程开启的该子线程)
  3. this->moveToThread(m_pThread);这个所做的操作,是把该类对象移到线程中进行运行。这种做法使得它所有的槽函数都是执行在新开辟的线程里面。
  4. QtEventLoop:事件循环实际上类似于一个事件队列,对列入的事件依次的进行处理,当时间做完而时间循环没有结束的时候,其实际上比较类似于一个不占用CPU事件的for(;;)循环。比如说如果想要将主线程等待100ms,总不能使用sleep吧,那样会导致GUI界面停止响应的,但是用事件循环就可以避免这一点。m_pTimer->start(1000)。这样就开启这个定时器了。

25. Qt的show() exec()区别?

show():
显示一个非模式对话框。控制权即刻返回给调用函数。
弹出窗口是否模式对话框,取决于modal属性的值。

exec():
显示一个模式对话框,并且锁住程序直到用户关闭该对话框为止。函数返回一个DialogCode结果。
在对话框弹出期间,用户不可以切换同程序下的其它窗口,直到该对话框被关闭。

模式对话框,就是在弹出窗口的时候,整个程序就被锁定了,处于等待状态,直到对话框被关闭。这时往往是需要对话框的返回值进行下面的操作。如:确认窗口(选择“是”或“否”)。
非模式对话框,在调用弹出窗口之后,调用即刻返回,继续下面的操作。这里只是一个调用指令的发出,不等待也不做任何处理。如:查找框。

26、用QT实现一个三角形的按钮,会如何实现?

  1. setIcon的方法。但这个方法,虽然现实上已经弄成了不规则图形了,但实际上,点击图形外的区域也是会触发的。
  2. setMask的方式也可以。
  3. 重写QPushButton.

27. 如何设置scroll Area的QSS?

label 是scroll Area里面的控件。

    ui->lblContent->setStyleSheet("QLabel{background-color:white;}");
    ui->scrollAreaWidget->setStyleSheet("QWidget {background-color:white;}");
    ui->scrollArea->setStyleSheet("QScrollArea {background-color:rgba(255,255,255,0);}");
    ui->scrollArea->viewport()->setStyleSheet("background-color:rgba(255,255,255,0);");

28. /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.20’ not found (required by /ics/lib/libopencv_dnn.so.3.4)

在这里插入图片描述

29. 电脑因为某种原因卡住,一动不动。

一般来说,你可以先尝试,看能否在这种状态下,进入安全模式,把要保存的文件,先拷贝出来,防止意外。
好了,接下来,你重启电脑。发现电脑一直在转圈圈。
那么,原因就是:你之前在使用电脑的时候,可能某些操作影响到了系统,所以,系统在重启的时候,一直想要恢复那个操作,但又没办法恢复,所以,就一直停在那里。
那么,你就要回忆,你什么操作影响到的系统,比如你是在编译文件,那么你就把这个工程依赖的一些库给转移掉,让他找不到那些库,就不会一直卡在那里。
但你要做上面这步操作之前,要先进入安全模式,如何进入呢?你就重启电脑三次,在每次出现那个平行四边形块的时候,就关掉电脑,继续重启。在第三次的时候,就可以进行系统维护了,建议你可以搜下 如何进入安全模式。然后,破坏那个卡住的情况,再重新重启,有可能就可以了,实在不行,如果那个软件影响不大,就卸载呗,也没啥办法。

参考:

  1. Qt的智能指针
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值