简体   繁体   中英

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 .
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.
Also the Widget class has a child element called tableWidget .

在此输入图像描述

Now I'm in addItem class, How to access to tableWidget element that is a child followed to Widget class?

Widget Class (.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)

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

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

Widget.h (mainwindow):

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

Widget.cpp (mainwindow):

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.

For example, if you want take text from QTableWidget , provide method for example

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:

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

where name is ui->nameLineEdit->text() and so on. Just take text from lineEdit and send it.

Catch it with special slot in Widget class. 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.

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.h:

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

dialog.cpp When user clicks we get data, emit signal and close dialog.

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

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

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:

在此输入图像描述

Now I set some data and clicked Additem button:

在此输入图像描述

As you can see, our connection works, data properly placed in the 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.

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:

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>

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. You could take your own Model class and have Qts view model auto update the UI when your view model changes. 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.

Disclaimer: I didn't actually try to compile any of this code, treat it as pesudo code ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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