13.4.2 选择信息的同步
Qt的Model/View框架允许多个视图对象显示同一个模型类对象中的数据集,这样,用户可以在不同的视图对象中查看数据集中不同部分的数据项。在这种情形下,用户往往希望在某个视图对象中选择了一些数据项之后,其他视图对象也应该把这些数据项显示为选中状态。也就是说,无论用户在哪个视图对象中执行了选择或者取消选择操作,其他视图对象也应该立即更新数据项的选择状态,以确保所有视图中同一个数据项的选择状态是一致的,这被称为选择信息的同步。
Qt的Model/View框架没有把数据项的选择状态直接存放在视图对象中,而是使用独立的类QItemSelectionModel专门维护数据项的选择信息,这种设计很容易实现选择信息的同步:我们只需要令多个视图对象共享同一个QItemSelectionModel对象,即可轻易地实现选择信息的同步。
如代码段13 18所示,行①、②调用两个视图对象的setModel()函数,令它们显示同一个模型类对象中的数据集。每当一个视图对象的setModel()函数被调用时,会有一个QItemSelectionModel对象被创建。而且,这个QItemSelectionModel对象的信号selectionChanged()会与视图对象的同名槽函数selectionChanged()绑定。一旦选择信息发生变化,视图对象会及时检测到这个变化并做相应的处理。
行③调用函数selectionModel()获取其中一个视图对象v2中的QItemSelectionModel对象,再调用另外一个视图对象v1的setSelectionModel()函数,令v1也使用这个QItemSelectionModel对象。当setSelectionModel()函数被调用时,QItemSelectionModel对象的信号selectionChanged()会和v1的同名槽函数selectionChanged()绑定。得益于Qt的信号与槽机制,同一个信号可以和多个槽函数绑定,因此,一旦选择信息发生变化,同一个信号可以触发两个视图对象中的槽函数,使得两个视图对象都可以更新显示,以反映最新的选择信息。
代码段13 18,同步两个视图对象中的选择信息,取自z:\examples\mvc\sync_selection\main.cpp。
- QStringList numbers;
- numbers << "One" << "Two" << "Three" << "Four" << "Five";
- QStringListModel model(numbers);
- QListView v1,v2;
- v1.setModel( &model ); ①
- v2.setModel( &model ); ②
- v1.setSelectionModel( v2.selectionModel() ); ③
每个视图对象在内部使用一个指针指向一个QItemSelectionModel对象。有的读者疑惑:行③令v1中的这个指针指向v2对应的QItemSelectionModel对象,那么v1中原先这个指针所指的QItemSelectionModel对象似乎成为一个"孤立对象",也就是说,不再有指针指向它,这是否会导致内存泄露?是否应该在行③之前先析构这个"孤立对象"?
得益于QObject的良好设计,以上问题不会发生。当应用程序创建QObject或其派生类的对象时,如果指定了这个对象的父对象,那么应用程序不必显式地析构这个对象。当父对象被析构时,这个对象会被自动析构。本例中的所有对象都是QObject对象。行①调用setModel()函数时会创建一个QItemSelectionModel对象,其父对象被设置为视图对象v1。因而,当整个程序退出时会析构v1,届时就会析构v1对应的那个"孤立对象"。