2

我刚开始使用Qt。我想制作一个带有自定义小部件的 GUI,可用于显示/编辑我的自定义数据类型。我还希望能够动态地创建/销毁这些小部件(而不破坏底层数据)。

我试图通过dataContainer在主 Window 类中存储我的数据项列表dataContainercustomWidget然后customWidget可以通过这个指针改变底层数据。

下面的代码允许用户重复地将dataContainer实例添加到列表中并编辑它们的每个“名称”。当我运行它时,只要我不实际编辑名称,一切都会正常工作,但如果我编辑名称然后单击“添加”按钮,则会出现段错误。此段错误发生在customWidgetduring delete myWidget;in的析构函数期间Window::add()

两个问题:

  1. 为什么这段代码会崩溃?我不允许像这样动态创建/销毁小部件吗?
  2. 有没有更合适的方法来做到这一点?

如果我在这里遗漏了一些基本的东西,我深表歉意,但是我一直在上下很多论坛和教程,但没有发现任何有用的东西。

主文件

#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"
4

1 回答 1

3

添加到布局的小部件不能直接删除。相反,您可以尝试以下代码,该代码从布局中删除特定小部件和相应的布局项:

QLayoutItem* item;
while ( ( item = mainLayout->takeAt( 0 ) ) != NULL )
{
    if(item->widget() == myWidget){
        delete item->widget();
        delete item;
    }
}
于 2013-01-09T07:43:04.033 回答