zoukankan      html  css  js  c++  java
  • 使用Qt编程的一些体会

    Qt是一个很灵活的框架,其优秀的跨平台特性、丰富的界面定制功能和简明的信号-槽大大的简化了编程工作,并让代码很简洁优雅,但是在实际项目中,还是会遇到一些问题

    1. 无边框窗口的移动问题

    如果只是为了“能用”,那么网上现成的这类代码很多,简单的参考一下就可以写出这样的代码:

    MyWidget::MyWidget(QWidget *parent) :
        QWidget(parent)
    {
        //...
        this->setFixedSize(this->size());
        this->setWindowFlags(Qt::FramelessWindowHint);
        this->m_isHold = false;
        //...
    }
    
    void MyWidget::mousePressEvent(QMouseEvent *pEvent)
    {
        if(pEvent->button() == Qt::LeftButton)
        {
            m_isHold = true;
            m_relativePoint = pEvent->globalPos() - this->pos();
        }
    }
    
    void MyWidget::mouseReleaseEvent(QMouseEvent *)
    {
        m_isHold = false;
    }
    
    void MyWidget::mouseMoveEvent(QMouseEvent *pEvent)
    {
        if(m_isHold)
        {
            this->move(pEvent->globalPos() - m_relativePoint);
        }
    }

    但是这种做法会导致一个很严重的问题,就是在鼠标拖动窗口的时候,可以把窗口拖到任务栏下面,联众游戏里面捆绑的联众助手就有这个问题。
    有一种网上流传的土办法可以解决此问题:

    this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);

    这样做的话,窗口的确不会被拖到任务栏下了,但是总在最前的窗口也不能让人满意。
    因为这个问题只会出现在Windows下,所以我们可以通过Win32 API来解决问题,MSDN里可以查到一个名叫ClipCursor的函数:

    BOOL WINAPI ClipCursor(_In_opt_  const RECT *lpRect);
    /*
    Parameters: lpRect [in, optional] Type: const RECT*
    A pointer to the structure that contains the screen coordinates
    of the upper-left and lower-right corners of the confining rectangle.
    If this parameter is NULL, the cursor is free to move anywhere on the screen.
    
    Return value: Type: BOOL
    If the function succeeds, the return value is nonzero.
    */

    这个函数接收一个RECT*类型的参数,限制鼠标指针的活动在这个RECT限制的范围内。
    于是我们有了以下的解决方案:

    //类声明:
    #include <windows.h>
    
    class MyWidget: public QWidget
    {
        Q_OBJECT
    //...
    private:
        RECT rtConfined;
        RECT rtDefault;
    //...
    }
    
    //构造函数里:
    {
    //...
        ::SystemParametersInfo(SPI_GETWORKAREA , 0 , &this->rtConfined , 0);
        ::GetWindowRect(::GetDesktopWindow() , &this->rtDefault);
    //...
    }
    
    //重写事件响应虚函数:
    void MyWidget::mousePressEvent(QMouseEvent *pEvent)
    {
    //...
        if(pEvent->button() == Qt::LeftButton)
        {
            m_isHold = true;
            m_relativePoint = pEvent->globalPos() - this->pos();
        }
        ::ClipCursor(&rtConfined);
    //...
    }
    
    void MyWidget::mouseReleaseEvent(QMouseEvent *)
    {
        m_isHold = false;
        ::ClipCursor(&rtDefault);
    }

    2. Qt4无边框窗口失去焦点的问题

    在项目从Qt5迁移到Qt4的过程中,出现过一个问题:一个无边框透明窗体,在showMinimized之后,点击任务栏图标,不会触发窗体的自动重绘,窗口表现为失去焦点
    设置窗体透明的代码如下:

    this->setWindowOpacity(1);
    QPalette pal = palette();
    pal.setColor(QPalette::Background, QColor(0x00,0xff,0x00,0x00));//Qt4里必须这样否则不透明
    this->setPalette(pal);
    this->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowMinimizeButtonHint|Qt::WindowSystemMenuHint);
    this->setAttribute(Qt::WA_TranslucentBackground, true);

    在中文网路上查找了很久也没有找到解决方案,后来改去爆栈上搜,也没看出个所以然,但是初步怀疑是无边框窗口的缘故,最后用Google去“site:qt-project.org”里看到了相关资料,这是一个 Qt4的bug,可以参考官网的链接
    Widget with Qt::FramelessWindowHint and Qt::WA_TranslucentBackground stops painting after minimize/restore
    按照说明,得到了如下的workaround:

    void MyWidget::showEvent(QShowEvent *pEvent)
    {
        QApplication::postEvent(this, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
        QWidget::showEvent(pEvent);
    }

    是的,就是这样,问题就解决了。

  • 相关阅读:
    java获取当前时间(年~~毫秒)
    python获取当前时间
    PyThon3运算符
    PyThon3中判断一个内容属于另一个内容("a" 在 “abcd”中
    PyThon3判断语句
    【BZOJ2460】元素(BJOI2011)-异或线性基+贪心
    【BZOJ3534】重建(SDOI2014)-矩阵树定理
    【BZOJ1227】虔诚的墓主人(SDOI2009)-线段树+离散化+组合数
    【BZOJ2815】灾难(ZJOI2012)-拓扑排序+建树+LCA
    【BZOJ2209】括号序列(JSOI2011)-Splay
  • 原文地址:https://www.cnblogs.com/intervention/p/4031850.html
Copyright © 2011-2022 走看看