美文网首页C++
14. QT合并标题和菜单栏--Apple的学习笔记

14. QT合并标题和菜单栏--Apple的学习笔记

作者: applecai | 来源:发表于2021-07-26 21:12 被阅读0次

    一,前言

    在上一篇blog13. QlistView显示iconfont--Apple的学习笔记中,我用QSS无法修改widget标题栏的颜色。此时突然想到之前看到过QT制作的无窗体工程。若无窗体就解决此问题了。并且我发现比如酷狗音乐等主界面好像都是工具栏标题栏合并的,所以我要尝试下。

    二,需求

    无标题栏,工具栏设置关闭应用程序的按钮即可。

    三,遇到的问题

    1. 如何隐藏标题栏?
    答:setWindowFlags(Qt::FramelessWindowHint)
    2. 无标题栏情况下如下移动主窗口?
    答:重写代替标题栏的控件的mouseEvent即可。我用menubar代替了Widget的标题栏。最关键的就是鼠标位置,要获取全局的,而不是相对主控件的位置。API为mapToGlobal。并且初始化的时候要传入主窗体win=parent;,通过win->setGeometry设置主窗体位置。

    void MenuC::mousePressEvent(QMouseEvent *ev)
    {
        QMenuBar::mousePressEvent(ev);
        if(ev->type() == QMouseEvent::MouseButtonPress)
        {
            m_StartMove= true;
            m_curPoint = mapToGlobal(ev->pos());
        }
    }
    
    void MenuC::mouseMoveEvent(QMouseEvent *ev)
    {
        QMenuBar::mouseMoveEvent(ev);
        if(m_StartMove)
        {
            QPoint step = mapToGlobal(ev->pos()) - m_curPoint;
            QPoint point =  step + win->geometry().topLeft();
            win->setGeometry(QRect(point, win->size()));
            m_curPoint += step;
        }
    }
    
    void MenuC::mouseReleaseEvent(QMouseEvent *ev)
    {
        QMenuBar::mouseReleaseEvent(ev);
        m_StartMove = false;
    }
    

    3. 点击菜单按钮也会移动主窗口,并且无法释放鼠标?
    答:这是因为重写鼠标事件没有禁止原来的菜单按下事件功能,所以按钮的时候做些判断若点击到菜单按钮则不触发移动功能即可。

    void MenuC::mousePressEvent(QMouseEvent *ev)
    {
        QMenuBar::mousePressEvent(ev);
        if(ev->type() == QMouseEvent::MouseButtonPress)
        {
            const QList<QAction*>& actions = this->actions();
            for (int i = 0; i < actions.size(); ++i)
            {
                QAction* pAction = actions.at(i);
                QRect rect = actionGeometry(pAction);
                if (rect.contains(ev->pos()))
                {
                    qDebug()<<ev->pos();
                }
                else
                {
                    m_StartMove= true;
                    m_curPoint = mapToGlobal(ev->pos());
                }
            }
        }
    }
    

    4. 重写事件的设计方法?
    答:由于这个鼠标是全局事件,我上面只能解决一个action问题,若再加几个menu和action依然存在问题。需要找到彻底的解决方法。一般可能想到的就是重写event,把自己需要处理的event单独拿出,其它继续传递。但是如果控件多的时候,就要重写很多event。这就要用到事件过滤器,eventfilter在event事件前做的过滤。可以使用一个事件过滤器,来判断是否需要调用event()函数,所以用eventfilter才是更好的方法。
    5. 如何使事件可以传递到top顶层父类?
    答:事件接受后就不会再向父类传递了。一般不使用event ->accept();和event->ignore();一般若忽略,则直接调用父类的事件。在closeEvent事件处理函数中,accept是关闭窗口,ignore是不关闭窗口,只有在closeEvent中才是这样。

    四,效果

    看上去界面效果不错吧~若要自己做最小化最大化按钮,可以用toolbutton或toolbar或pushbutton等。我只是自己做了一个MenuC类,继承了MenuBar类。


    image.png
    效果.gif

    五,小结

    体验了下自定义标题栏的效果。主要困难就是拖动事件收到影响,纠结了些时间。主要一开始搜索的是标题栏和菜单栏合并,其实搜索QT自定义标题栏,可以找到很多设计案例可以参考的。了解了全局事件处理的关键技术installEventFilter。

    相关文章

      网友评论

        本文标题:14. QT合并标题和菜单栏--Apple的学习笔记

        本文链接:https://www.haomeiwen.com/subject/svdimltx.html