C++ 如何跨共享一个模型的多个Qt小部件进行通信

C++ 如何跨共享一个模型的多个Qt小部件进行通信,c++,qt,model-view-controller,C++,Qt,Model View Controller,我在一个主窗口中有一个集合小部件,所有这些小部件都可以处理模型上的一点数据,我在下面附上了一张结构图。目前,只有树小部件可以访问模型,并且还具有树视图。和其他小部件的通信是通过信号和插槽完成的。当在树中进行新选择时,屏幕上的每个其他小部件都会更改以表示新选择的树节点。这是可行的,但是通过一个小部件向所有其他小部件发送信号非常麻烦 我希望将树使用的模型传递给所有其他小部件,并使其不受模型在对其进行任何更改时发送的信号的影响。因此,可以通过模型本身进行通信,而不是让所有类相互发送信号 我已经在主窗口

我在一个主窗口中有一个集合小部件,所有这些小部件都可以处理模型上的一点数据,我在下面附上了一张结构图。目前,只有树小部件可以访问模型,并且还具有树视图。和其他小部件的通信是通过信号和插槽完成的。当在树中进行新选择时,屏幕上的每个其他小部件都会更改以表示新选择的树节点。这是可行的,但是通过一个小部件向所有其他小部件发送信号非常麻烦

我希望将树使用的模型传递给所有其他小部件,并使其不受模型在对其进行任何更改时发送的信号的影响。因此,可以通过模型本身进行通信,而不是让所有类相互发送信号

我已经在主窗口类的构造函数中创建了一个模型并将其传递给树和其他小部件,但是我不确定应该如何从这一点开始,因为我对MVC相对不熟悉。tree类是目前唯一具有视图的类,我是否需要向其他类添加视图,以便能够访问在选择某个字段时发出的信号,或者模型是否足够

如果您有任何意见,我将不胜感激,谢谢


是的,如果有什么变化,通知模型并使其发出信号,在相关小部件中订阅该信号。换句话说,将小部件彼此解耦删除小部件订阅,只订阅模型。

是的,如果有更改,通知模型并使其发出信号,在相关小部件中订阅该信号。换句话说,将小部件彼此解耦删除小部件订阅,只订阅模型。

选择不是模型的属性,而是视图的属性。可以将多个视图附着到单个模型,每个视图显示不同的“项目”。因此,没有现成的方法来表示模型本身的选择发生了变化

有一个专门的类,它精确地处理您需要的内容:跟踪跨多个视图的单个模型上的选择

您可以将数据模型包装在选择模型中,并以此为基础进行通信,例如:

MyMainWindow::MyMainWindow() {
   myModel = new MyModel;
   treeView = new MyTreeView(myModel);
   QItemSelectionModel *selectionModel = new QItemSelectionModel(myModel);
   treeView->setSelectionModel(selectionModel);
   detailWidget = new MyDetailWidget(this, selectionModel);
}

////////////

MyDetailWidget::MyDetailWidget(QWidget *parent, QItemSelectionModel *selectionModel) {
   // React to changed selection
   connect(selectionModel, &QItemSelectionModel::currentChanged, this, 
     [=](auto current, auto /*previous*/) { 
       updateView(current);
     }
   );

   // React to change in selected item
   connect(selectionModel->model(), &QAbstractItemModel::dataChanged, this,
     [=](auto topLeft, auto bottomRight, auto /*roles*/) {
       QItemSelection sel(topLeft, bottomRight);
       if (sel.contains(selectionModel->currentIndex()) {
          updateView(selectionModel->currentIndex());
       }
     }
   );
}

void MyDetailWidget::updateView(const QModelIndex &idx) {
   // Assume some label on this widget
   m_name->setText(idx.data(Qt::DisplayRole).toString());
}

选择不是模型的属性,而是视图的属性。可以将多个视图附着到单个模型,每个视图显示不同的“项目”。因此,没有现成的方法来表示模型本身的选择发生了变化

有一个专门的类,它精确地处理您需要的内容:跟踪跨多个视图的单个模型上的选择

您可以将数据模型包装在选择模型中,并以此为基础进行通信,例如:

MyMainWindow::MyMainWindow() {
   myModel = new MyModel;
   treeView = new MyTreeView(myModel);
   QItemSelectionModel *selectionModel = new QItemSelectionModel(myModel);
   treeView->setSelectionModel(selectionModel);
   detailWidget = new MyDetailWidget(this, selectionModel);
}

////////////

MyDetailWidget::MyDetailWidget(QWidget *parent, QItemSelectionModel *selectionModel) {
   // React to changed selection
   connect(selectionModel, &QItemSelectionModel::currentChanged, this, 
     [=](auto current, auto /*previous*/) { 
       updateView(current);
     }
   );

   // React to change in selected item
   connect(selectionModel->model(), &QAbstractItemModel::dataChanged, this,
     [=](auto topLeft, auto bottomRight, auto /*roles*/) {
       QItemSelection sel(topLeft, bottomRight);
       if (sel.contains(selectionModel->currentIndex()) {
          updateView(selectionModel->currentIndex());
       }
     }
   );
}

void MyDetailWidget::updateView(const QModelIndex &idx) {
   // Assume some label on this widget
   m_name->setText(idx.data(Qt::DisplayRole).toString());
}