我刚开始使用Qt。我想制作一个带有自定义小部件的 GUI,可用于显示/编辑我的自定义数据类型。我还希望能够动态地创建/销毁这些小部件(而不破坏底层数据)。
我试图通过dataContainer
在主 Window 类中存储我的数据项列表dataContainer
(customWidget
然后customWidget
可以通过这个指针改变底层数据。
下面的代码允许用户重复地将dataContainer
实例添加到列表中并编辑它们的每个“名称”。当我运行它时,只要我不实际编辑名称,一切都会正常工作,但如果我编辑名称然后单击“添加”按钮,则会出现段错误。此段错误发生在customWidget
during delete myWidget;
in的析构函数期间Window::add()
。
两个问题:
- 为什么这段代码会崩溃?我不允许像这样动态创建/销毁小部件吗?
- 有没有更合适的方法来做到这一点?
如果我在这里遗漏了一些基本的东西,我深表歉意,但是我一直在上下很多论坛和教程,但没有发现任何有用的东西。
主文件
#include <QApplication>
#include "window.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window mainWindow;
mainWindow.show();
return app.exec();
}
窗口.h
#ifndef WINDOW_H
#define WINDOW_H
#include <QWidget>
#include "customwidget.h"
class Window : public QWidget {
Q_OBJECT
public:
Window();
public slots:
void add();
private:
// the main data structure
QList<dataContainer> dataList;
// the widget that displays the custom data
customWidget *myWidget;
QVBoxLayout *mainLayout;
QPushButton *addButton;
};
#endif
窗口.cpp
#include <QtGui>
#include "window.h"
Window::Window(){
// start with a single piece of data in the list
dataContainer newData;
dataList.append(newData);
// create layout container
mainLayout = new QVBoxLayout(this);
mainLayout->setAlignment(Qt::AlignTop);
// make the Add button, and connect its clicked() SIGNAL
// to our add() SLOT
addButton=new QPushButton(tr("Add"),this);
connect(addButton,SIGNAL(clicked()),this,SLOT(add()));
mainLayout->addWidget(addButton);
// create a custom widget to display our data and
// give it a pointer to the data it will display/modify
myWidget = new customWidget(this,&(dataList.last()) );
mainLayout->addWidget(myWidget);
setLayout(mainLayout);
}
void Window::add(){
// create a new piece of data, and add to the list
dataContainer newData;
dataList.append(newData);
// debug: show the current list
qDebug() << "Data List(" << dataList.size() << ")";
for (int i=0;i<dataList.size();i++){
qDebug() << dataList[i].getName().c_str();
}
// delete the old widget
delete myWidget;
// and make a new widget with the new data
myWidget = new customWidget(this,&(dataList.last()) );
mainLayout->addWidget(myWidget);
}
#include "window.moc"
自定义小部件.h
#ifndef CUSTOMWIDGET_H
#define CUSTOMWIDGET_H
#include <QWidget>
#include <QtGui>
#include <string>
class dataContainer {
private:
std::string name;
public:
dataContainer(){name="oooh";};
std::string getName()const{return name;};
std::string setName(const std::string& n){name=n;};
};
class customWidget : public QWidget {
Q_OBJECT
private:
dataContainer *data;
public slots:
void nameChangedSlot(const QString&);
public:
customWidget(QWidget *parent, dataContainer *d);
};
#endif
customwidget.cpp
#include "customwidget.h"
customWidget::customWidget(QWidget *parent, dataContainer *d) : QWidget(parent) {
// store a pointer to the data that we want to alter
data = d;
// create an edit box and initialize it with the data name
QVBoxLayout *mainLayout=new QVBoxLayout(this);
QLineEdit *edit=new QLineEdit(QString::fromStdString(data->getName()),this);
mainLayout->addWidget(edit);
connect(edit,SIGNAL(textChanged(const QString&)),this,SLOT(nameChangedSlot(const QString&)));
}
void customWidget::nameChangedSlot(const QString& name){
// alter the contents of our data based on the changed string
data->setName(name.toStdString());
}
#include "customwidget.moc"