【笔记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
相关推荐
山岚的运维笔记9 小时前
SQL Server笔记 -- 第18章:Views
数据库·笔记·sql·microsoft·sqlserver
lpruoyu10 小时前
【Android第一行代码学习笔记】Android架构_四大组件_权限_持久化_通知_异步_服务
android·笔记·学习
wdfk_prog11 小时前
[Linux]学习笔记系列 -- [drivers][mmc][mmc_sdio]
linux·笔记·学习
果果燕11 小时前
今日学习笔记:双向链表、循环链表、栈
笔记·学习·链表
觉醒大王11 小时前
AI写的青基中了
人工智能·笔记·深度学习·学习·职场和发展·学习方法
明月醉窗台11 小时前
qt使用笔记六之 Qt Creator、Qt Widgets、Qt Quick 详细解析
开发语言·笔记·qt
Hello_Embed14 小时前
libmodbus 移植 STM32(USB 串口后端篇)
笔记·stm32·单片机·嵌入式·freertos·libmodbus
张祥64228890414 小时前
RTKLIB源码和理论结合分析笔记三
笔记
日更嵌入式的打工仔14 小时前
0欧电阻作用
笔记
R_.L14 小时前
【QT】常用控件(按钮类控件、显示类控件、输入类控件、多元素控件、容器类控件、布局管理器)
开发语言·qt