Qt 杂项(Qwt、样式等)

Qt隐藏窗口边框

this->setWindowFlags(Qt::FramelessWindowHint);

Qt模态框

this->setWindowModality(Qt::ApplicationModal);

QLable隐藏border

代码中设置

lable->setStyleSheet("border:0px");

或者UI中直接设置样式:“border:0px”

Qwt开源控件

QwtDial 刻度盘显示汉字

  1. QwRoundScaleDraw中增加一个QMap<double,QString> 属性用于存储刻度对应的汉字描述

    private:
        // 添加代码片段
    	QMap<double,QString> lableMap_ ;
        // 添加代码片段
    public:
        // 添加代码片段
    	void setLableMap(QMap<double,QString> maps){ lableMap_ = maps;}
        // 添加代码片段
           
    
  2. 修改QwRoundScaleDraw中的drawLable函数

    在这里插入图片描述

  3. 在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操作;包括定时器
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值