首页 > 解决方案 > 如何在共享模型的多个 Qt Widget 之间进行通信

问题描述

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

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

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

我很感激任何意见,谢谢。

小部件结构

标签: c++qtmodel-view-controller

解决方案


选择不是模型的属性,而是视图的属性。多个视图可以附加到单个模型,每个视图显示不同的“项目”。因此,没有开箱即用的方法来表示模型本身的选择变化。

有一个专门的QItemSelectionModel类,可以准确地处理您需要的内容:跟踪跨多个视图的单个模型的选择。

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

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

推荐阅读