提升CustomQScrollArea分段错误

时间:2013-11-14 20:32:04

标签: qt

我的实际用例非常重要,所以我提供了一个重现分段错误的小例子:

我有继承QScrollArea的类CustomScrollArea:

customscrollarea.h

class CustomScrollArea : public QScrollArea
{
    Q_OBJECT
public:
    explicit WarxingScrollArea(QWidget* parent=0);
    void segFaultThrowingMethod();
private:
    QLabel* dynamicallyCreatedLabel;
};

customscrollarea.cpp

CustomScrollArea::CustomScrollArea(QWidget* parent) : QScrollArea(parent)
{
    dynamicallyCreatedLabel = new QLabel;
    setWidget(dynamicallyCreatedLabel);

    //this call will _not_ cause a seg fault
    segFaultThrowingMethod();
}

void CustomScrollArea::segFaultThrowingMethod()
{
    dynamicallyCreatedLabel->setText("Some text");
}

我有一个MainWindow类,其中包含以下内容:

mainwindow.h

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
};

mainwindow.cpp

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

    //this call will cause a seg fault
    ui->customScrollArea->segFaultThrowingMethod();
}

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

MainWindow的.ui文件包含一个提升为CustomQScrollArea的QScrollArea。它的名字是“customScrollArea”。

当我启动应用程序时,CustomScrollArea :: segFaultThrowingMethod()的第一次调用发生在CustomScrollArea的Ui :: MainWindow :: customScrollArea的构造函数中,并且无事故地传递。但是,当MainWindow调用ui-> customScrollArea-> segFaultThrowingMethod()时,会发生分段错误。

请注意,分段错误不是由于CustomScrollArea :: dynamicCreatedLabel为空(如建议的here)。我得到的最好线索是,如果MainWindow动态实例化CustomScrollArea而不是从Ui :: MainWindow获取它,则不会发生此问题。但是,我希望能够在Qt Designer中使用QScrollAreas提升为CustomScrollAreas。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

Qt Designer会自动为任何滚动区域创建内部窗口小部件。默认情况下,此窗口小部件称为“scrollAreaWidgetContents”,在Qt Designer的窗口小部件树中可见。 Designer生成的Ui::MainWindow类为您创建CustomScrollArea并执行setWidget来设置其内容。调用CustomScrollArea构造函数后,此操作在setupUi中发生。但QScrollArea获得其内部窗口小部件的所有权。调用setWidget时,前一个滚动区域的内部窗口小部件(如果有)将被解除并销毁。因此,在setWidget内调用setupUi会导致先前创建的QLabel被破坏,并且dynamicallyCreatedLabel指针变为无效。

无法在Qt Designer中删除“scrollAreaWidgetContents”。解决方法是向窗体添加一个窗口小部件并将其提升为CustomScrollArea类。 Qt Designer不会知道CustomScrollArea实际上是QScrollArea并且不会自己调用setWidget。唯一的副作用是您将无法在Qt Designer中设置滚动区域特定属性并访问其插槽。但是你可以从代码中做到这一点,所以这不是一个大问题。