1

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

我有继承 QScrollArea 的类 CustomScrollArea:

海关滚动区域.h

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

customcrollarea.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 类:

主窗口.h

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

主窗口.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::dynamicallyCreatedLabel 为空(如此建议)。我得到的最好线索是,如果 MainWindow 动态实例化 CustomScrollArea 而不是从 Ui::MainWindow 获取它,则不会发生此问题。但是,我希望能够在 Qt Designer 中使用提升为 CustomScrollAreas 的 QScrollAreas。

谢谢你的帮助!

4

1 回答 1

1

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

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

于 2013-11-15T00:53:02.200 回答