简体   繁体   English

如何从另一个对话框类访问窗口小部件类

[英]How to access to widget class from another dialog class

Firstly, I have two classes. 首先,我有两节课。 The First class called Widget , and the second class called addItem . First类称为Widget ,第二个类称为addItem
The Widget class is the main class(main window) of application ui, but the addItem class is just window, appears when click on add person to add new contact. Widget类是应用程序ui的main class(main window) ,但是addItem类只是窗口,当点击添加人员添加新联系人时出现。
Also the Widget class has a child element called tableWidget . Widget类还有一个名为tableWidget的子元素。

在此输入图像描述

Now I'm in addItem class, How to access to tableWidget element that is a child followed to Widget class? 现在我在addItem类中, 如何访问tableWidget元素,这是一个跟随Widget类的子元素?

Widget Class (.h) 小部件类(.h)

namespace Ui {
    class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void resizeEvent(QResizeEvent *event);

private slots:
    void on_delete_btn_clicked();   
    void on_add_btn_clicked();

private:
    Ui::Widget *ui;
};

addItem Class (.h) addItem类(.h)

namespace Ui {
    class addItem;
}

class addItem : public QDialog
{
    Q_OBJECT

public:
    explicit addItem(QWidget *parent = 0);
    ~addItem();

private slots:
    void on_addBtn_clicked();

private:
    Ui::addItem *ui;
};

Edit 编辑

The following method belong to addItem class. 以下方法属于addItem类。

addItem.cpp: addItem.cpp:

void addItem::on_addBtn_clicked(){
    emit mySignal(ui->name_txt->text(), ui->address_txt->text(), ui->phoneNum_txt->text(), ui->mobileNum_txt->text());
    Widget *widget = new Widget;
    connect(this, SIGNAL(mySignal(QString,QString,QString,QString)), widget, SLOT(addMyItem(QString,QString,QString,QString)));
    this->close();
}

See also the rest of the code that I wrote : 另请参阅我编写的其余代码:

addItem.h: addItem.h:

signals:
    void mySignal(QString, QString, QString, QString);

Widget.h (mainwindow): Widget.h (主窗口):

private slots:
    void addMyItem(QString, QString, QString, QString);

Widget.cpp (mainwindow): Widget.cpp (主窗口):

void Widget::addMyItem(QString name, QString address, QString phone_number, QString mobile_number){
    qDebug() << name << "\n" << address << "\n" << phone_number << "\n" << mobile_number;
}

Setting 设置

public:
    Ui::Widget *ui;

isn't good practice, so you can use getters and setters. 这不是一个好习惯,所以你可以使用getter和setter。

For example, if you want take text from QTableWidget , provide method for example 例如,如果您想从QTableWidget获取文本,请提供示例方法

QString Widget::getCellData(int row, int col)
{
    return ui->tableWidget->item(row,col)->text();
}

To set data: 设置数据:

void Widget::setCellData(int row, int col, QString txt)
{
    //create item if you need
    ui->tableWidget->item(row,col)->setText(txt);
}

and so on. 等等。 I hope you will understand main idea and how to do it. 我希望你能理解主要思想以及如何去做。

But you can use also signals and slots: 但你也可以使用信号和插槽:

For example user clicks on add button and you want add new data in table, then emit from addItem button signal: 例如,用户点击添加按钮,你想在表中添加新数据,然后从addItem按钮信号发出:

 emit mySignal(name, address, phone , mobile);

where name is ui->nameLineEdit->text() and so on. 其中name是ui->nameLineEdit->text()等等。 Just take text from lineEdit and send it. 只需从lineEdit中获取文本并发送即可。

Catch it with special slot in Widget class. Widget类中使用特殊插槽捕获它。 In this slot you can create new row and set data. 在此插槽中,您可以创建新行和设置数据。

void Widget::mySlot(QString name,QString address,QString phone ,QString mobile)
{
    //create cells and set data in it
}

And of course you should connect mySignal from addItem class to mySlot in Widget class. 当然,您应该将mySignaladdItem类连接到Widget类中的mySlot

addItem *mDialog = new addItem;
connect(mDialog,SIGNAL(mySignal(QString,QString,QString,QString)),this,SLOT(mySlot(QString,QString,QString,QString)));

Conclusion: I think, you should use signals and slots. 结论:我认为,你应该使用信号和插槽。


Edit 编辑

Explanation in detail: 详细说明:

You have Dialog class and mainwindow: 你有Dialog类和mainwindow:

dialog.h: dialog.h:

signals:
    void mySignal(QString,QString,QString,QString);

dialog.cpp When user clicks we get data, emit signal and close dialog. dialog.cpp当用户点击我们获取数据时,发出信号并关闭对话框。

void Dialog::on_addItemButton_clicked()
{
    emit mySignal(ui->lineEdit_2->text(),ui->lineEdit_3->text(),ui->lineEdit_4->text(),ui->lineEdit_5->text());
    this->close();
}

mainwindow.h mainwindow.h

private slots:
      void addMyItems(QString,QString,QString,QString);

mainwindow.cpp mainwindow.cpp

void MainWindow::addMyItems(QString name,QString address,QString phone ,QString mobile)
{
    ui->tableWidget->setRowCount(ui->tableWidget->rowCount() + 1);//increase row count by 1

    int row = ui->tableWidget->rowCount() - 1;

    //set all data in cells
    ui->tableWidget->setItem(row,0,new QTableWidgetItem(name));
    ui->tableWidget->setItem(row,1,new QTableWidgetItem(address));
    ui->tableWidget->setItem(row,2,new QTableWidgetItem(phone));
    ui->tableWidget->setItem(row,3,new QTableWidgetItem(mobile));
}

Slot for button in mainwindow which opens dialog: 主窗口中的按钮插槽,打开对话框:

void MainWindow::on_Add_clicked()
{
    Dialog *dia = new Dialog;//our dialog
    dia->setAttribute(Qt::WA_DeleteOnClose);//we don't want memory leak
    //connection
    connect(dia,SIGNAL(mySignal(QString,QString,QString,QString)),this,SLOT(addMyItems(QString,QString,QString,QString)));
    dia->setModal(true);//you can use modal window instead of exe()
    dia->show();
}

Result: 结果:

I clicked on Add button and get dialog: 我点击了Add按钮并进入对话框:

在此输入图像描述

Now I set some data and clicked Additem button: 现在我设置一些数据并单击Additem按钮:

在此输入图像描述

As you can see, our connection works, data properly placed in the tableWidget. 如您所见,我们的连接正常工作,数据正确放置在tableWidget中。

The way I normally handle these things is quite non Qt-ish, but it makes unit testing easier. 我通常处理这些事情的方式非常简单,但它使单元测试更容易。 I have something like MVC (model-view-controller), but in Qt the V and C are one. 我有类似MVC(模型 - 视图 - 控制器)的东西,但在Qt中V和C是一个。

For example the model could be: 例如,模型可以是:

class Record
{
public:
  std::string mName;
  std::string mAddress;
  std::string mPhoneNumber;
  std::string mMobileNumber;
};

class Model
{
public:
  void AddRecord(std::unique_ptr<Record> rec)
  {
      mRecords.emplace_back(std::move(rec));
  }

  const Record* ItemAt(size_t index) const
  {
     if (index > mRecords.size()) { return nullptr; }
     return mRecords(index);
  }

  size_t NumRecords() const
  {
    return mRecords.size();
  }
private:
  std::vector<std::unique_ptr<Record> mRecords;
};

Then in your main function you can construct a model and pass it to your main/view window: 然后在main函数中,您可以构建一个模型并将其传递给主/视图窗口:

int main( int argc, char **argv )
{
    // Create app instance
    QApplication a( argc, argv );

    Model model;
    MainWindow mainWindow(model); // MainWindow stores a reference to the model
    mainWindow.exec();

And the when you create the sub dialog simply pass that the model too. 当你创建子对话框时,也只是传递了模型。 Or have it return a std::unique_ptr<Record> 或者让它返回一个std::unique_ptr<Record>

void MainWindow::on_Add_clicked()
{
    Dialog *dia = new Dialog(this, mModel);//Where mModel is the Model instance reference we passed to Widget in main()
    dia->exec();
}

Its worth noting that Qt comes with its own model classes for the views. 值得注意的是,Qt带有自己的视图模型类。 You could take your own Model class and have Qts view model auto update the UI when your view model changes. 您可以使用自己的Model类,并在视图模型更改时让Qts视图模型自动更新UI。 This is much more advanced though. 但这要先进得多。 For now you could just manually keep your model in sync with your UI, ie if you add a record or remove a record from model, then update your table widget. 现在,您可以手动使模型与UI保持同步,即,如果您添加记录或从模型中删除记录,则更新表格小部件。

Disclaimer: I didn't actually try to compile any of this code, treat it as pesudo code ;) 免责声明:我实际上并没有尝试编译任何此代码,将其视为pesudo代码;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM