在Qt框架里,组合模式的设计应用较为广泛,以下是一些具体的例子:
1. QObject
及其派生类体系
QObject
是Qt中绝大多数类的基类,它构建了一个树形的对象结构,这和组合模式的理念相契合。每个 QObject
对象都可以有父对象和子对象,借助 setParent()
方法能够构建对象树。当父对象被销毁时,其所有子对象也会被自动销毁。
cpp
#include <QApplication>
#include <QWidget>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 创建一个父窗口
QWidget *parentWidget = new QWidget();
parentWidget->setWindowTitle("Parent Widget");
// 创建一个子标签,将父窗口作为其父对象
QLabel *childLabel = new QLabel("This is a child label", parentWidget);
parentWidget->show();
return a.exec();
}
在这个例子中,QWidget
作为父对象,QLabel
作为子对象。当 parentWidget
被销毁时,childLabel
也会自动被销毁。
2. QGraphicsItem
及其派生类
在Qt的图形视图框架中,QGraphicsItem
是所有图形项的基类,它支持组合模式。图形项可以包含子图形项,从而构建出复杂的图形场景。
cpp
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QGraphicsEllipseItem>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 创建场景
QGraphicsScene scene;
// 创建一个矩形图形项作为父项
QGraphicsRectItem *parentRect = new QGraphicsRectItem(0, 0, 100, 100);
scene.addItem(parentRect);
// 创建一个椭圆图形项作为子项
QGraphicsEllipseItem *childEllipse = new QGraphicsEllipseItem(20, 20, 50, 50, parentRect);
// 创建视图并显示场景
QGraphicsView view(&scene);
view.show();
return a.exec();
}
在这个例子中,QGraphicsRectItem
是父图形项,QGraphicsEllipseItem
是子图形项。子图形项的位置和变换是相对于父图形项的。
3. QMenu
和 QAction
QMenu
类用于创建菜单,QAction
类用于表示菜单项。一个 QMenu
可以包含多个 QAction
,还可以包含子菜单,这形成了一个树形结构。
cpp
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow window;
// 创建菜单栏
QMenuBar *menuBar = window.menuBar();
// 创建主菜单
QMenu *fileMenu = menuBar->addMenu("File");
// 创建菜单项
QAction *openAction = new QAction("Open", &window);
QAction *saveAction = new QAction("Save", &window);
// 将菜单项添加到主菜单
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
// 创建子菜单
QMenu *importMenu = fileMenu->addMenu("Import");
QAction *importTextAction = new QAction("Import Text", &window);
importMenu->addAction(importTextAction);
window.show();
return a.exec();
}
在这个例子中,QMenuBar
是根,QMenu
是树枝节点,QAction
是叶子节点。通过这种方式,可以构建出复杂的菜单系统。
4. QTreeWidget
和 QTreeWidgetItem
QTreeWidget
是一个用于显示树形结构数据的控件,QTreeWidgetItem
表示树中的项。可以通过 addChild()
方法将一个 QTreeWidgetItem
添加到另一个 QTreeWidgetItem
作为子项,从而构建树形结构。
cpp
#include <QApplication>
#include <QTreeWidget>
#include <QTreeWidgetItem>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTreeWidget treeWidget;
treeWidget.setColumnCount(1);
// 创建根项
QTreeWidgetItem *rootItem = new QTreeWidgetItem(&treeWidget);
rootItem->setText(0, "Root");
// 创建子项
QTreeWidgetItem *childItem1 = new QTreeWidgetItem(rootItem);
childItem1->setText(0, "Child 1");
QTreeWidgetItem *childItem2 = new QTreeWidgetItem(rootItem);
childItem2->setText(0, "Child 2");
treeWidget.show();
return a.exec();
}
在这个例子中,QTreeWidget
是容器,QTreeWidgetItem
构成了树形结构,根项可以有多个子项,子项也可以有自己的子项。
5. QFileInfo 与 QDir 类
QFileInfo 类用于获取文件或目录的信息,而 QDir 类用于操作目录及其内容。QDir 可以包含多个文件和子目录,这类似于组合模式中的树枝节点,而文件则类似于叶子节点。
cpp
#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QDebug>
// 递归遍历目录
void traverseDirectory(const QDir &dir, int level = 0) {
QString indent(level * 4, ' ');
QFileInfoList entries = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo &entry : entries) {
if (entry.isDir()) {
qDebug() << indent + "+ " + entry.fileName();
traverseDirectory(QDir(entry.absoluteFilePath()), level + 1);
} else {
qDebug() << indent + "- " + entry.fileName();
}
}
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QDir rootDir("your_directory_path");
if (rootDir.exists()) {
traverseDirectory(rootDir);
}
return a.exec();
}
在上述代码中,traverseDirectory
函数递归地遍历指定目录及其子目录。QDir
就像树枝节点,它可以包含多个文件(叶子节点)和子目录(新的树枝节点)。