QThread之quit() 和 terminate()
- quit() 通知线程的事件循环退出...如果线程没有事件循环,就啥都不做。
- terminate() 可以简单理解为强制退出
示例:
class MyThread:public QThread
{
Q_OBJECT
protected:
void run()
{
//处理1
//处理2
int ret = exec(); //线程事件循环
qDebug() << "return code:" << ret;
}
};
假设1 线程正在执行 处理1 的位置
如果调用quit(),线程会一直走到最后,然后线程退出。
如果调用terminate(),线程可能会执行完处理1直接退出,也可能没执行完处理1直接退出。
如果不调用quit和terminate,线程执行完处理1和处理2,进入事件循环不会退出。
假设2 线程执行到exec()的位置
如果调用quit(),线程会一直走到最后,然后线程退出。
如果调用terminate(),线程直接退出,而且不会打印最后一行
如果不调用quit和terminate,处于事件循环不会退出。
假设3 注释调exec()
quit()不会起到任何作用,且线程执行完处理1和处理2直接退出。
特别注意:通常情况下我们以继承的方式创建线程都忽略不写exec(),所以会误认为quit()没有作用!!!
QMetaObject::invokeMethod
官方文档举例一:
QMetaObject::invokeMethod(thread, "quit", Qt::QueuedConnection);
官方文档举例二:
QString retVal;
QMetaObject::invokeMethod(obj, "compute", Qt::DirectConnection,
Q_RETURN_ARG(QString, retVal),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7));
从上面的例子,我们只能看到invokeMethod的调用方式和起到异步调用的效果。那什么情况我们用这种方式呢?比如线程更改UI的时候会很方便。
void run()
{
//...
QMetaObject::invokeMethod(parent(),"updateUI",Qt::QueuedConnection,Q_ARG(QString,"修改"));
exec();
}
假设主程序中有个槽函数updateUI(QString)用来更新UI上的显示,通过上述调用的时候updateUI函数的执行会自动在主进程的状态执行,避免的线程操作UI的隐患。这样写的好处就是减少了信号槽的定义关联的麻烦。
快速打包Qt程序
比如说完成了一个Qt程序 'xxx.exe',需要把它打包发布,一个一个找依赖耗时耗力还没有保证。这时我们就需要借助Qt5.11.1\5.11.1\msvc2017_64\bin\windeployqt.exe,它能自动把程序依赖拷贝到当前的目录里去,就像这样
windeployqt xxx.exe
十六进制字符转十进制的方法
QByteArray array;
array.resize(2);
array[0] = 0x07;
array[1] = 0xE3;
qDebug() << array.toHex().data(); //07e3
bool ok;
qDebug() << array.toHex().toInt(&ok,16); //2019
一句话理解下installEventFilter
ui.pushbutton->installEventFilter(this);
把ui.pushbutton的消息事件放在当前这个类this来处理
Qt父窗口与子窗口摩擦的一些小毛病
一、通过继承QWidget用来作为子类使用,发现setStyleSheet不管事了~~~写以下几行解决
void FirstChild::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
QStyleOption o;
o.initFrom(this);
style()->drawPrimitive(QStyle::PE_Widget,&o,&painter,this);
}
二、鼠标点击到子窗口上,希望无视子窗口,直接由父窗口来处理鼠标事件~~~加一句属性即可
setAttribute(Qt::WA_TransparentForMouseEvents);
三、父窗口中存在多个子窗口,希望某个子窗口显示在最前面或最后面~~~这些函数会帮到你
void QWidget::stackUnder(QWidget *w)
//放在w后面,注意两个子窗口要是同级的
//例如:a.stackUnder(b),b在前显示
[slot] void QWidget::raise()
//提到最前显示
[slot] void QWidget::lower()
//提到最后显示
QTreeWidget下查询节点
//递归查找
QTreeWidgetItem *Dialog::findChildItemRecursion(QTreeWidgetItem *parent, QString name)
{
if(parent->text(0) == name)
return parent;
int nCount = parent->childCount();
for(int i=0;i<nCount;i++)
{
QTreeWidgetItem* childItem = findChildItemRecursion(parent->child(i),name);
if(childItem != NULL)
{
return childItem;
}
}
return NULL;
}
//遍历查找
QTreeWidgetItem *Dialog::findChildItemTraverse(QTreeWidgetItem *parent, QString name)
{
QTreeWidgetItemIterator iter(parent);
while(*iter)
{
if((*iter)->text(0) == name)
{
return (*iter);
}
++iter;
}
return NULL;
}
Qt设置窗口透明
一、设置Flags和Attribute的方式,子控件不受影响
setWindowFlags(Qt::FramelessWindowHint);//windows下要加
setAttribute(Qt::WA_TranslucentBackground,true);
二、通过设置窗口透明度,子控件也受影响
setWindowOpacity(0.0);
三、设置子控件透明
QGraphicsOpacityEffect* effect = new QGraphicsOpacityEffect(this);
effect->setOpacity(0.5);
ui->pushButton->setGraphicsEffect(effect);
Qt样式表引用图片---路径问题
相对路径写法一
this->setStyleSheet("border-image:url(image/pic.jpg)");
相对路径写法二
this->setStyleSheet("border-image:url(./image/pic.jpg)");
从Qrc中加载
this->setStyleSheet("border-image:url(:/image/pic.jpg)");
Qt打日志
先来认识下这几个弟兄
int func( char* prev_param, ...);
三个点可以理解为接收多个参数用的
typedef char * va_list;
由于多个参数都是按顺序存放在堆栈中,这个变量可以理解为指向第一个参数
void va_start( va_list va_list, prev_param );
可以认为是给va_list赋值
void va_end( va_list va_list);
最后还免不了要释放
使用重载分别实现了两种传参的方法,上代码:
#include <QThread>
#include <QTime>
#include <QFile>
#include <QDir>
#include <windows.h>
void writeLog(QString msg)
{
//系统当前时间
QString strTime = QTime::currentTime().toString("hh:mm:ss.zzz");
//进程ID
DWORD lpId = GetCurrentProcessId();
//创建目录
QString strDir("c:/log/");
QDir dir(strDir);
if(!dir.exists())
dir.mkdir(strDir);
//写日志
QFile file("c:/log/logs.log");
if(file.open(QIODevice::WriteOnly | QIODevice::Append))
{
QTextStream stream(&file);
stream << QString("%1---PID:[%2]---: %3\r\n").arg(strTime).arg(lpId).arg(msg);
file.close();
}
}
void writeLog(char* pMsg,...)
{
va_list argList;
va_start(argList,pMsg);
QString strResult = QString::vasprintf(pMsg,argList);
va_end(argList);
writeLog(strResult);
}
//调用
writeLog(const_cast<char*>("%s %s"),"hello","Qt"); //void writeLog(char* pMsg,...)
writeLog(QString("%1 %2").arg("hello").arg("C++")); //void writeLog(QString msg)
(未完待续...)