【笔记1-10】Qt bug记录:dockwidget通过raise在最前面显示,toolbar的拓展菜单失效

  • 问题的场景和流程都比较奇怪,主界面上有多个dockwidget,堆叠在右侧,toolbar上有一些action按钮,用于控制dock的显示和非显示,当显示时会在slot函数中调用raise函数,使dock窗口置于最前面
  • 问题现象是,当调整toolbar的长度时,toolbar会把部分action放到拓展菜单中,拓展菜单的按钮不能连续点击,而拓展菜单外的action没问题
  • 而且这个问题只在dockwidget堆叠时发生,如果只有一个dock或浮动状态时,不会发生
  • dockwindow堆叠显示就是下图的圈起来的状态,多个窗口都在同一个位置,通过点击tab标签可以切换窗口
  • toolbar拓展菜单的问题现象如下,第二排和第三排的按钮无法连续点击,点击1次或2次,到最前面显示后就不能点击了,等鼠标离开,拓展区收回,再次打开时就复位了
  • 经过一番调查发现,问题出在工具栏按钮的slot函数中,这里的处理是,如果需要不显示就使用hide,如果要显示就调用show和raise
    如果将raise函数删除的话,问题现象就不会发生,也就是没有raise的效果但是可以点击
  • 接下来要调查raise的源码了,如下图(qwidget.cpp)

    subtractOpaqueSiblings和invalidateBackingStore两个函数计算了需要重绘的区域,并通过最后一行的sendEvent将重绘事件(rePaint)发送了
    通过debug看了重绘区域的坐标,到这里还没问题
  • 接下来sendEvent通过多层调用,调用了void QMainWindowLayout::tabChanged()
  • 如下图,tabChanged在最后一行调用了centralWidget的raise函数,这个raise和刚才的是同一个
    也就是说,centralWidget也被重绘了,而toolbar的拓展区域就在其中,所以被一起重绘了,因此导致无法点击,非拓展区没有问题
    而单个窗口和浮动状态不会调用tabChanged,所以没问题
  • 为了验证以上理论猜测,在toolbar和centralWidget之间再加一块测试区,也就是下图
  • 代码是通过再追加一个toolbar实现的
  • 测试结果是在测试区的toolbar拓展菜单的按钮可以连续点击,而测试区以外,也就是centralWidget的toolbar拓展菜单的按钮无法连续点击
  • 经过以上调查,这个问题基本无解了。。。 也不知道这么奇怪又小众的问题会不会有人遇到

测试代码

main.cpp

c 复制代码
#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{

    QApplication a(argc, argv);

    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.cpp

c 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setCentralWidget(new QWidget(this));

    m_pTBWindow = addToolBar(tr("Window"));
    m_pTBWindow->setObjectName("Window");
        addToolBarBreak();
    m_pTBTest = addToolBar(tr("test"));
    m_pTBTest->setObjectName("test");
    m_pTBTest->setStyleSheet("background-color: rgb(0, 196, 255);");
    m_pTBTest->setMinimumWidth(100);
    m_pTBTest->setMaximumWidth(800);

    m_pTBTest->setFixedHeight(20);

    m_pActTest1111DockShow           = new QAction(this);
    m_pActTest1111DockShow->setText(tr("Test1111"));
    m_pActTest1111DockShow->setCheckable(true);



    m_pActTest2222DockShow           = new QAction(this);
    m_pActTest2222DockShow->setText(tr("Test2222"));
    m_pActTest2222DockShow->setCheckable(true);


    m_pActTest3333WinDockShow           = new QAction(this);
    m_pActTest3333WinDockShow->setText(tr("Test3333"));
    m_pActTest3333WinDockShow->setCheckable(true);

    m_pActTest4444DockShow           = new QAction(this);
    m_pActTest4444DockShow->setText(tr("Test4444"));
    m_pActTest4444DockShow->setCheckable(true);

    m_pActTest5555DockShow           = new QAction(this);
    m_pActTest5555DockShow->setText(tr("Test5555"));
    m_pActTest5555DockShow->setCheckable(true);

    m_pActTest6666DockShow           = new QAction(this);
    m_pActTest6666DockShow->setText(tr("Test6666"));
    m_pActTest6666DockShow->setCheckable(true);

    m_pActTest7777DockShow           = new QAction(this);
    m_pActTest7777DockShow->setText(tr("Test7777"));
    m_pActTest7777DockShow->setCheckable(true);

    m_pActTest8888DockShow           = new QAction(this);
    m_pActTest8888DockShow->setText(tr("Test8888"));
    m_pActTest8888DockShow->setCheckable(true);

    m_pActTest9999DockShow           = new QAction(this);
    m_pActTest9999DockShow->setText(tr("Test9999"));
    m_pActTest9999DockShow->setCheckable(true);

    m_pActTest10101010DockShow           = new QAction(this);
    m_pActTest10101010DockShow->setText(tr("Test10101010"));
    m_pActTest10101010DockShow->setCheckable(true);

    m_pActTest20202020DockShow           = new QAction(this);
    m_pActTest20202020DockShow->setText(tr("Test20202020"));
    m_pActTest20202020DockShow->setCheckable(true);

    m_pTBWindow->addAction(m_pActTest1111DockShow);
    m_pTBWindow->addAction(m_pActTest2222DockShow);
    m_pTBWindow->addAction(m_pActTest3333WinDockShow);
    m_pTBWindow->addAction(m_pActTest4444DockShow);
    m_pTBWindow->addAction(m_pActTest6666DockShow);
    m_pTBWindow->addAction(m_pActTest7777DockShow);
    m_pTBWindow->addAction(m_pActTest8888DockShow);
    m_pTBWindow->addAction(m_pActTest9999DockShow);
    m_pTBWindow->addAction(m_pActTest10101010DockShow);
    m_pTBWindow->addAction(m_pActTest20202020DockShow);

    m_pTest1111Dock = new mydock("Test1111");
    m_pTest1111Dock->setObjectName("Test1111");
    m_pTest1111Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest1111Dock->setAccessibleName("Test1111Window");
    m_pTest1111Dock->setWidget(new QWidget(m_pTest1111Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest1111Dock);

    m_pTest2222Dock = new mydock("Test2222");
    m_pTest2222Dock->setObjectName("Test2222");
    m_pTest2222Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest2222Dock->setAccessibleName("Test2222");
    m_pTest2222Dock->setWidget(new QWidget(m_pTest2222Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest2222Dock);

    m_pTest3333WinDock = new mydock("Test3333");
    m_pTest3333WinDock->setObjectName("Test3333");
    m_pTest3333WinDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest3333WinDock->setAccessibleName("Test3333");
    m_pTest3333WinDock->setWidget(new QWidget(m_pTest3333WinDock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest3333WinDock);

    m_pTest4444Dock = new mydock("Test4444");
    m_pTest4444Dock->setObjectName("Test4444");
    m_pTest4444Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest4444Dock->setAccessibleName("Test4444");
    m_pTest4444Dock->setWidget(new QWidget(m_pTest4444Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest4444Dock);

    m_pTest20202020Dock = new mydock("Test20202020");
    m_pTest20202020Dock->setObjectName("Test20202020");
    m_pTest20202020Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest20202020Dock->setAccessibleName("Test20202020");
    m_pTest20202020Dock->setWidget(new QWidget(m_pTest20202020Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest20202020Dock);

    m_pTest5555Dock = new mydock("Test5555");
    m_pTest5555Dock->setObjectName("Test5555");
    m_pTest5555Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest5555Dock->setAccessibleName("Test5555");
    m_pTest5555Dock->setWidget(new QWidget(m_pTest5555Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest5555Dock);


    m_pTest6666Dock = new mydock("Test6666");
    m_pTest6666Dock->setObjectName("Test6666");
    m_pTest6666Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest6666Dock->setAccessibleName("Test6666");
    m_pTest6666Dock->setWidget(new QWidget(m_pTest6666Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest6666Dock);

    m_pTest7777Dock = new mydock("Test7777");
    m_pTest7777Dock->setObjectName("Test7777");
    m_pTest7777Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest7777Dock->setAccessibleName("Test7777");
    m_pTest7777Dock->setWidget(new QWidget(m_pTest7777Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest7777Dock);

    m_pTest8888Dock = new mydock("Test8888");
    m_pTest8888Dock->setObjectName("Test8888");
    m_pTest8888Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest8888Dock->setAccessibleName("Test8888");
    m_pTest8888Dock->setWidget(new QWidget(m_pTest8888Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest8888Dock);

    m_pTest9999Dock = new mydock("Test9999");
    m_pTest9999Dock->setObjectName("Test9999");
    m_pTest9999Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest9999Dock->setAccessibleName("Test9999");
    m_pTest9999Dock->setWidget(new QWidget(m_pTest9999Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest9999Dock);

    m_pTest10101010Dock = new mydock("Test10101010");
    m_pTest10101010Dock->setObjectName("Test10101010");
    m_pTest10101010Dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    m_pTest10101010Dock->setAccessibleName("Test10101010");
    m_pTest10101010Dock->setWidget(new QWidget(m_pTest10101010Dock));  // 隶セ鄂ョ蜀�螳ケ
    addDockWidget(Qt::RightDockWidgetArea, m_pTest10101010Dock);




    connect(m_pActTest1111DockShow, SIGNAL(triggered(bool)), m_pTest1111Dock, SLOT(slotActivate(bool)));
    connect(m_pActTest2222DockShow, SIGNAL(triggered(bool)), m_pTest2222Dock, SLOT(slotActivate(bool)));
    connect(m_pActTest3333WinDockShow, SIGNAL(triggered(bool)), m_pTest3333WinDock, SLOT(slotActivate(bool)));
    connect(m_pActTest4444DockShow, SIGNAL(triggered(bool)), m_pTest4444Dock, SLOT(slotActivate(bool)));
    connect(m_pActTest6666DockShow, SIGNAL(triggered(bool)), m_pTest6666Dock, SLOT(slotActivate(bool)));
    connect(m_pActTest7777DockShow, SIGNAL(triggered(bool)), m_pTest7777Dock, SLOT(slotActivate(bool)));
    connect(m_pActTest8888DockShow, SIGNAL(triggered(bool)), m_pTest8888Dock, SLOT(slotActivate(bool)));
    connect(m_pActTest9999DockShow, SIGNAL(triggered(bool)), m_pTest9999Dock, SLOT(slotActivate(bool)));
    connect(m_pActTest10101010DockShow, SIGNAL(triggered(bool)), m_pTest10101010Dock, SLOT(slotActivate(bool)));
    connect(m_pActTest20202020DockShow, SIGNAL(triggered(bool)), m_pTest20202020Dock, SLOT(slotActivate(bool)));

}

MainWindow::~MainWindow()
{
    delete ui;
}

mainwindow.h

c 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QToolBar>
#include <QMouseEvent>



#include "mydock.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    QToolBar*   m_pTBWindow;
    QToolBar*   m_pTBTest;
    QAction*    m_pActTest1111DockShow;
    QAction*    m_pActTest2222DockShow;
    QAction*    m_pActTest3333WinDockShow;
    QAction*    m_pActTest4444DockShow;
    QAction*    m_pActTest5555DockShow;
    QAction*    m_pActTest6666DockShow;
    QAction*    m_pActTest7777DockShow;
    QAction*    m_pActTest8888DockShow;
    QAction*    m_pActTest9999DockShow;
    QAction*    m_pActTest10101010DockShow;
    QAction*    m_pActTest20202020DockShow;

    mydock*       m_pTest1111Dock;
    mydock*		m_pTest2222Dock;
    mydock*       m_pTest3333WinDock;
    mydock*       m_pTest4444Dock;
    mydock*         m_pTest20202020Dock;
    mydock*       m_pTest5555Dock;
    mydock*       m_pTest6666Dock;
    mydock*       m_pTest7777Dock;
    mydock*       m_pTest8888Dock;
    mydock*       m_pTest9999Dock;
    mydock*               m_pTest10101010Dock;







private:
    Ui::MainWindow *ui;

private slots:
protected:
    // 鮠�譬�遘サ蜉ィ莠倶サカ
    void mousePressEvent(QMouseEvent *event) override {
        QPoint pos = event->pos();  // 逶ク蟇ケ莠守ェ怜哨逧�蝮先��
        QPoint globalPos = event->globalPos();  // 蜈ィ螻€蝮先��

        qDebug() << pos;


        QWidget::mousePressEvent(event);
    }

};
#endif // MAINWINDOW_H

mydock.cpp

c 复制代码
#include "mydock.h"

mydock::mydock(const QString &title) {

    m_pTitleBarWidget = new QWidget(this);
    m_pTitleBarWidget->setFixedHeight(25+8);
    m_pTitleBarWidget->setAccessibleName("DockWidgetTitle");


    m_pLabel = new QLabel(m_pTitleBarWidget);
    m_pLabel->setIndent( 4 );
    m_pLabel->setText(title);
    m_pLabel->setFixedHeight(25+1);


    setStyleSheet("background-color: rgb(201, 196, 255);");

}



void mydock::slotActivate(bool value)
{
    if(m_bIsActive)
    {
        hide();
        m_bIsActive = false;
    }
    else
    {
        show();
        raise();

        m_bIsActive = true;
    }
}

mydock.h

c 复制代码
#ifndef MYDOCK_H
#define MYDOCK_H
#include <QDockWidget>
#include <QLabel>
class mydock : public QDockWidget
{
        Q_OBJECT

public:
    mydock(const QString &title);
    bool m_bIsActive = false;;
    QWidget*        m_pTitleBarWidget;
    QLabel*         m_pLabel;
private slots:
    void slotActivate(bool);
};

#endif // MYDOCK_H
相关推荐
奥特曼_ it2 小时前
【数据分析+机器学习】基于机器学习的招聘数据分析可视化预测推荐系统(完整系统源码+数据库+开发笔记+详细部署教程)✅
笔记·数据挖掘·数据分析
四维碎片3 小时前
QSettings + INI 笔记
笔记·qt·算法
zzcufo3 小时前
多邻国第5阶段17-18学习笔记
笔记·学习
BlackWolfSky4 小时前
鸿蒙中级课程笔记4—应用程序框架进阶1—Stage模型应用组成结构、UIAbility启动模式、启动应用内UIAbility
笔记·华为·harmonyos
中屹指纹浏览器4 小时前
指纹浏览器性能优化实操——多实例并发与资源占用管控
经验分享·笔记
了一梨5 小时前
SQLite3学习笔记5:INSERT(写)+ SELECT(读)数据(C API)
笔记·学习·sqlite
jrlong5 小时前
DataWhale大模型基础与量化微调task5学习笔记(第 3 章:大模型训练与量化_模型量化实战)
笔记·学习
Sarvartha5 小时前
Routing(路由与分支)学习笔记
笔记·学习
Yu_Lijing6 小时前
《图解HTTP》笔记与读后感(上)
网络·笔记·网络协议·http
Gain_chance6 小时前
23-学习笔记尚硅谷数仓搭建-ODS层业务全量表、增量表结构设计及数据装载脚本
数据仓库·hive·笔记·学习