【问题标题】:How to access to widget class from another dialog class如何从另一个对话框类访问小部件类
【发布时间】:2014-11-25 03:50:09
【问题描述】:

首先,我有两节课。 第一类称为Widget,第二类称为addItem
Widget 类是应用程序 ui 的 main class(main window),但 addItem 类只是窗口,在单击添加人员添加新联系人时出现。
Widget 类还有一个名为 tableWidget 的子元素。

现在我在addItem 班级,如何访问tableWidget 元素,它是Widget 班级的孩子?

小部件类 (.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 类 (.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;
};

编辑

以下方法属于addItem类。

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();
}

另请参阅我编写的其余代码:

addItem.h:

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

Widget.h(主窗口):

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

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;
}

【问题讨论】:

    标签: c++ qt class user-interface qt5


    【解决方案1】:

    设置

    public:
        Ui::Widget *ui;
    

    不是很好的做法,因此您可以使用 getter 和 setter。

    例如,如果你想从QTableWidget获取文本,请提供方法示例

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

    设置数据:

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

    等等。我希望你能理解主要思想以及如何去做。

    但你也可以使用信号和槽:

    例如用户点击添加按钮,你想在表中添加新数据,然后从 addItem 按钮信号发出:

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

    其中名称是ui-&gt;nameLineEdit-&gt;text() 等等。只需从 lineEdit 中获取文本并发送即可。

    使用Widget 类中的特殊插槽捕获它。在此槽中,您可以创建新行并设置数据。

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

    当然,您应该将 mySignaladdItem 类连接到 Widget 类中的 mySlot

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

    结论:我认为,你应该使用信号和槽。


    编辑

    详细解释:

    你有 Dialog 类和主窗口:

    dialog.h:

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

    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();
    }
    

    主窗口.h

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

    主窗口.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));
    }
    

    主窗口中打开对话框的按钮槽:

    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();
    }
    

    结果:

    我点击了添加按钮并得到对话框:

    现在我设置了一些数据并点击了 Additem 按钮:

    如您所见,我们的连接正常,数据正确放置在 tableWidget 中。

    【讨论】:

    • 谢谢,第一种方式 我知道 setter 和 getter,但是为什么你将 Ui::Widget *ui; 更改为 public,以及如何从 @987654342 访问它@ 班级。 第二种方式对我来说仍然很复杂。
    • @LionKing 我认为第一种方法是错误的。我写道,这是不好的做法。但是请告诉我,据我所知,您从小部件类调用 addItem 窗口,对吗?如果是这样,你应该使用第二种方式,我可以详细解释。
    • 关于您的询问,是的,这样addItem addItemWidget; addItemWidget.exec();。 但是除了signal &amp; slot之外没有其他方法可以从另一个类中获取一些数据吗?
    • @LionKing 我更新了我的答案,有详细解释,请看。此外,我添加了截图以显示一切正常。
    • 没问题。但我仍然不明白数据库问题。但我会尝试解决它。谢谢你的帮助
    【解决方案2】:

    我通常处理这些事情的方式是非常非 Qt-ish,但它使单元测试更容易。我有类似 MVC(模型-视图-控制器)的东西,但在 Qt 中,V 和 C 是一个。

    例如,模型可以是:

    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;
    };
    

    然后在您的主函数中,您可以构建一个模型并将其传递给您的主/视图窗口:

    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();
    

    当您创建子对话框时,也只需传递模型即可。或者让它返回一个std::unique_ptr&lt;Record&gt;

    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();
    }
    

    值得注意的是,Qt 带有自己的视图模型类。您可以使用自己的 Model 类并让 Qts 视图模型在您的视图模型更改时自动更新 UI。不过,这要先进得多。现在,您可以手动保持模型与 UI 同步,即,如果您从模型中添加记录或删除记录,然后更新表格小部件。

    免责声明:我实际上并没有尝试编译任何代码,将其视为伪代码;)

    【讨论】:

    • 谢谢,但是MVC 现在不能,因为我的应用程序不是由MVC 构建的。
    • 我知道,这就是为什么我说 Qt MVC 是可选的,我在这里发布的您自己的 MVC 仍然可以轻松完成。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    相关资源
    最近更新 更多