QResizeEvent 导致 SIGSEGV

Posted

技术标签:

【中文标题】QResizeEvent 导致 SIGSEGV【英文标题】:QResizeEvent causes SIGSEGV 【发布时间】:2014-08-04 13:00:35 【问题描述】:

我的目的是使用一个名为overlay.h 的类在Widget (MarbleWidget) 的顶部添加一个矩形框和文本。下面是我的 GUI 代码。我试图删除所有不必要的部分:

ma​​inwindow.cpp

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)

    setupUi(this);


MainWindow::~MainWindow()



void MainWindow::resizeEvent(QResizeEvent *event)

    overlay->resize(event->size());   //////////////// CAUSES SIGSEGV!!!!!!!!!!!!!
    event->accept();


void MainWindow::setupUi(QMainWindow *MainWindow)

    MainWindow->showMaximized();
    QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    sizePolicy.setHorizontalStretch(0);
    sizePolicy.setVerticalStretch(0);
    sizePolicy.setHeightForWidth(MainWindow->sizePolicy().hasHeightForWidth());
    MainWindow->setSizePolicy(sizePolicy);
    MainWindow->setTabShape(QTabWidget::Rounded);

    QWidget *centralwidget = new QWidget(MainWindow);
    centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
    sizePolicy.setHeightForWidth(centralwidget->sizePolicy().hasHeightForWidth());
    centralwidget->setSizePolicy(sizePolicy);
    centralwidget->setLayoutDirection(Qt::LeftToRight);

    QGridLayout *gridLayout_4 = new QGridLayout(centralwidget);
    gridLayout_4->setObjectName(QString::fromUtf8("gridLayout_4"));

    QSplitter *splitter_4 = new QSplitter(centralwidget);
    splitter_4->setObjectName(QString::fromUtf8("splitter_4"));
    splitter_4->setOrientation(Qt::Horizontal);

    QTabWidget *tabWidget_2 = new QTabWidget(splitter_4);
    tabWidget_2->setObjectName(QString::fromUtf8("tabWidget_2"));
    sizePolicy.setHeightForWidth(tabWidget_2->sizePolicy().hasHeightForWidth());
    tabWidget_2->setSizePolicy(sizePolicy);
    tabWidget_2->setMaximumSize(QSize(443, 16777));
    tabWidget_2->setAutoFillBackground(true);
    tabWidget_2->setTabPosition(QTabWidget::West);
    tabWidget_2->setTabShape(QTabWidget::Rounded);
    tabWidget_2->setIconSize(QSize(30, 16));

    QWidget *tab_10 = new QWidget();
    tab_10->setObjectName(QString::fromUtf8("tab_10"));
    QGridLayout *gridLayout = new QGridLayout(tab_10);
    gridLayout->setObjectName(QString::fromUtf8("gridLayout"));
    QVBoxLayout  *verticalLayout_4 = new QVBoxLayout();
    verticalLayout_4->setObjectName(QString::fromUtf8("verticalLayout_4"));
    QHBoxLayout *horizontalLayout_7 = new QHBoxLayout();
    horizontalLayout_7->setObjectName(QString::fromUtf8("horizontalLayout_7"));
    QLabel *label_3 = new QLabel(tab_10);
    label_3->setObjectName(QString::fromUtf8("label_3"));
    horizontalLayout_7->addWidget(label_3);

    verticalLayout_4->addLayout(horizontalLayout_7);
    QTreeView *treeView_4 = new QTreeView(tab_10);
    treeView_4->setObjectName(QString::fromUtf8("treeView_4"));
    QStandardItemModel *standardModel = new QStandardItemModel ;
    QStandardItem *rootNode = standardModel->invisibleRootItem();
    treeView_4->setModel(standardModel);
    verticalLayout_4->addWidget(treeView_4);
    gridLayout->addLayout(verticalLayout_4, 0, 0, 1, 1);

    tabWidget_2->addTab(tab_10, QString());
    treeView_4->raise();

    Marble::MarbleWidget* MarbleWidget = new Marble::MarbleWidget(splitter_4);

    splitter_4->addWidget(MarbleWidget);
    splitter_4->setStretchFactor(0,0);
    splitter_4->setStretchFactor(1,6);
    gridLayout_4->addWidget(splitter_4, 0, 0, 1, 1);

    MainWindow->setCentralWidget(centralwidget);
    MarbleWidget->raise();
    tabWidget_2->raise();

    overlay = new Overlay(MarbleWidget);
    overlay->raise();

    QMetaObject::connectSlotsByName(MainWindow);
 // setupUi

overlay.h

    #include <QWidget>
    #include <QPainter>

    class Overlay : public QWidget
    
    public:
        Overlay(QWidget *parent);

    protected:
        void paintEvent(QPaintEvent *event);
    ;

overlay.cpp

#include "overlay.h"

Overlay::Overlay(QWidget *parent)
: QWidget(parent)

    setPalette(Qt::transparent);
    setAttribute(Qt::WA_TransparentForMouseEvents);


void Overlay::paintEvent(QPaintEvent *event)

    QFont font;
    font.setStyleHint(QFont::Helvetica, QFont::PreferAntialias);
    font.setPointSize(10);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(QColor(10, 10, 10, 255));
    painter.fillRect(QRect(50, 50, 100, 100), QColor(100, 100, 100, 120));
    painter.setFont(font);
    painter.drawText(20, 20,  "hi..............................");

问题是overlay-&gt;resize(event-&gt;size()); 在核心运行该行时会导致SIGSEGV

代码有什么问题,我该如何解决?

【问题讨论】:

不是 100% 确定,但看起来调整叠加层的大小会导致主窗口也被调整大小。由于这发生在调整大小处理程序中,因此很可能会递归调用它并最终导致堆栈溢出。 @Frédéric Hamidi,感谢您的解释。您是否看到任何阻止 resize() 调整主窗口大小的方法/技巧? 我对 Qt 不够熟悉,无法为您提供灵丹妙药。我会仔细检查覆盖的新大小——也许你必须减去一些边框宽度以防止父级也调整大小。您还可以使用布尔成员变量保护您的调整大小处理程序,以防止它在调整叠加层大小时重新进入,但我不确定结果是否适合您。 当我通过调试器运行代码时,它会在第一次到达'overlay->resize(event->size())'时获取SIGSEGV Kuba Ober,我把基本布局留在了代码上,已经去掉了很多不必要的东西。代码长了 5 倍。随意编辑问题。顺便说一句,您对布局的回答让我受益匪浅,感谢您的帖子。 【参考方案1】:

问题由freenode的Thiago解决。

他指出MainWindow-&gt;showMaximized(); 导致resize() 事件在overlay 初始化之前发生。删除该行或将其移至初始化后即可解决问题。

【讨论】:

如果你在调试器下运行它,问题就会得到解决。回溯可以查明问题所在。调用堆栈包含:setupUishowMaximizedresizeEvent。或者,如果您按照应有的方式将代码最小化,您将删除showMaximized 行,问题就会消失。所以,你忽略了解决它的两种方法:/【参考方案2】:

查看官方文档:QWidget, Qt5resize 方法。在这里你可以阅读

警告:resizeEvent() 内调用resize()setGeometry() 会导致无限递归。

你做的完全一样。为了避免无限递归,您可以分别使用 SIGSEGV(难度降序,true-way 降序):

Overlay 中覆盖您的resizeEvent() 并在MainWindowresizeEvent 中评论该行; 在MainWindowresizeEvent 发出类似mainWindowSizeChanged(QSize) 的信号并将其连接到Overlay 的插槽; 在MainWindowresizeEvent 中执行QTimer::singleShot(...),所以它会在给定的时间间隔后调用给定的槽。

【讨论】:

仅当您为同一个小部件调用 resize 时才适用。在这种情况下不适用。

以上是关于QResizeEvent 导致 SIGSEGV的主要内容,如果未能解决你的问题,请参考以下文章

在 Symbian/Qt 中检测手机方向变化的问题

qt中怎么设置按钮的位置 固定在右上角 最大化和普通大小都在右上角

amazon redshift 并发写入导致插入记录,导致重复

FileHandler 创建会导致 NoSuchFileException 导致缺少 .lck

导致非标准行为的 #pragma 是不是会导致 __STDC__ 宏未定义为 1?

为啥 const int main = 195 会导致程序正常工作,但没有 const 会导致分段错误?