Qt隐藏窗口边框
this->setWindowFlags(Qt::FramelessWindowHint);
Qt模态框
this->setWindowModality(Qt::ApplicationModal);
QLable隐藏border
代码中设置
lable->setStyleSheet("border:0px");
或者UI中直接设置样式:“border:0px”
Qwt开源控件
QwtDial 刻度盘显示汉字
-
QwRoundScaleDraw中增加一个QMap<double,QString> 属性用于存储刻度对应的汉字描述
private: // 添加代码片段 QMap<double,QString> lableMap_ ; // 添加代码片段 public: // 添加代码片段 void setLableMap(QMap<double,QString> maps){ lableMap_ = maps;} // 添加代码片段
-
修改QwRoundScaleDraw中的drawLable函数
-
在QwtDial中设置QwRoundScaleDraw
效果图:红色模糊部分是设置的汉字
QwtDial 指针自定义
QwtDial 的指针是由QwtDialNeedle类绘制的,自定指针也就是实现QwtDialNeedle的子类
继承QwtDialNeedle只需要实现drawNeedle函数
drawNeedle( QPainter* painter, double length, QPalette::ColorGroup colorGroup ) const
示例:
void drawNeedle( QPainter* painter, double length, QPalette::ColorGroup colorGroup ) const{
const qreal width = qRound( length / 3.0 );
QPainterPath path[4];
path[0].lineTo( length, 0.0 );
path[0].lineTo( 0.0, width / 2 );
path[1].lineTo( length, 0.0 );
path[1].lineTo( 0.0, -width / 2 );
path[2].lineTo( -length, 0.0 );
path[2].lineTo( 0.0, width / 2 );
path[3].lineTo( -length, 0.0 );
path[3].lineTo( 0.0, -width / 2 );
const int colorOffset = 10;
const QColor darkColor = Qt::black;
const QColor lightColor = Qt::yellow;
QColor color[4];
color[0] = darkColor.lighter( 100 + colorOffset );
color[1] = darkColor.darker( 100 + colorOffset );
color[2] = lightColor.lighter( 100 + colorOffset );
color[3] = lightColor.darker( 100 + colorOffset );
painter->setPen( Qt::NoPen );
for ( int i = 0; i < 4; i++ )
{
painter->setBrush( color[i] );
painter->drawPath( path[i] );
}
}
QwtSlider 刻度显示汉字
需要修改QwtScaleDraw的源码,增加一个QMap<double,QString> 属性用于存储刻度对应的汉字描述
private:
// 添加代码片段
QMap<double,QString> lableMap_ ;
// 添加代码片段
public:
// 添加代码片段
void setLableMap(QMap<double,QString> maps){ lableMap_ = maps;}
// 添加代码片段
修改QwtScaleDraw中的drawLable
QwtSlider 自定义滑块形状
滑块是通过drawHandle函数绘制;可以通过一个函数指针,将外部绘制滑块的逻辑引入,替换默认绘制逻辑
函数指针定义(qwt_slider.h):
主要参数:handleRect,绘制滑块的区域,根据handleRect的坐标范围进行自定义绘制
orientation,表示QwtSlider控件是水平绘制,还是垂直绘制
QwtSlider添加函数SetDrawFunc
drawHandle函数修改:
QT数字格式化
// 10进制式化为指定宽度的16进制字符,位数不足补0
int a = 10;
int b=234;
QString msg=QString("test%1%2").
arg(a,2,16,QLatin1Char('0')).
arg(a,4,16,QLatin1Char('0'))
// msg test0a00ea
记录一次Qt加载耗时资源,弹出提示框的处理过程
问题
Qt主窗体中有一段处理比较耗时的代码,启动后界面要卡一段时间;用户体验不友好
解决思路
创建一个提示窗口(提示加载中,可以用动图或者进度条,目的是提示后台正在加载);把主窗体中的处理耗时的代码放到一个线程里;启动线程前先加载提示窗口,然后启动线程,线程执行的最后隐藏加载窗口。(这种处理思路在 winform 百试不爽)
遇到的问题
与winform框架不同的是,Qt在子线程中不得操作主界面的UI(会报错);提示窗口是在主线程中创建的,子线程中不能操作(主线程show出提示窗口,子线程不能直接hide)。所以隐藏提示窗口还是要回到主线程中(winform中有专门的函数可以子线程操作回归到主线程;Qt中可以使用信号槽的机制,将操作转回到主线程上)
Qt信号操作的连接类型(connect的第五个参数)
-
Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用Qt::DirectConnection类型。如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。
-
Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数和信号发送者在同一线程。效果看上去就像是直接在信号发送位置调用了槽函数,效果上看起来像函数调用,同步执行。emit语句后面的代码将在与信号关联的所有槽函数执行完毕后才被执行。
无论槽函数所属对象在哪个线程,槽函数都在发射信号的线程内执行。(可以理解为同步)
-
Qt::QueuedConnection:信号发出后,信号会暂时被放到一个消息队列中,需等到接收对象所属线程的事件循环取得控制权时才取得该信号,然后执行和信号关联的槽函数,这种方式既可以在同一线程内传递消息也可以跨线程操作。emit语句后的代码将在发出信号后立即被执行,无需等待槽函数执行完毕。槽函数在接收者所依附线程执行。(可以理解为异步)
-
Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。而且接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。(跨线程同步)
-
Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是为了避免重复连接。
处理过程
// 初始化连接 Qt::QueuedConnection 参数很重要
connect(this,SIGNAL(Signal1()),this,SLOT(Slot1()),Qt::QueuedConnection);
connect(this,SIGNAL(Signal2()),this,SLOT(Slot2()),Qt::QueuedConnection);
// 将耗时函数抽离出来
auto func = [&](){
// 耗时操作
emit Signal1() ;
// 耗时操作
emit Signal2() ;
// ...
}
// 线程中(th)不能有操作UI的代码,不能有Qtimer的操作!!!
std::thread th(func);
loadingFrm->show();
th.detach();
void Slot1(){
loadingFrm->hide();
}
void Slot2(){
// 其他ui操作;包括定时器
}