Qtを始めたばかりです。カスタム データ型の表示/編集に使用できるカスタム ウィジェットを備えた GUI を作成したいと考えています。また、これらのウィジェットを動的に作成/破棄できるようにしたいと考えています (基になるデータを破棄することなく)。
dataContainer
データ項目のリスト ( ) をメインの Window クラスに格納し、このポインターを格納するdataContainer
ウィジェット ( ) のコンストラクターにポインターを渡すことで、これを達成しようとしましたcustomWidget
。次にcustomWidget
、このポインターを介して基になるデータを変更できます。
以下のコードにより、ユーザーは繰り返しdataContainer
インスタンスをリストに追加し、それぞれの「名前」を編集できます。これを実行すると、実際に名前を編集しない限りすべて正常に動作しますが、名前を編集してから [追加] ボタンをクリックすると、segfault が発生します。この segfault は、 during のデストラクタ中に発生customWidget
しdelete myWidget;
ますWindow::add()
。
2 つの質問:
- このコードがクラッシュするのはなぜですか? このようなウィジェットを動的に作成/破棄することは許可されていませんか?
- これを達成するためのより適切な方法はありますか?
ここに欠けている基本的なものがある場合はお詫びしますが、多くのフォーラムやチュートリアルを行ったり来たりしましたが、役立つものは何も見つかりませんでした.
main.cpp
#include <QApplication>
#include "window.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Window mainWindow;
mainWindow.show();
return app.exec();
}
window.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"
customwidget.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"