C++

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

2021-07-26  本文已影响0人  applecai

一,前言

在上一篇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。

上一篇下一篇

猜你喜欢

热点阅读