QBrush 详解

QBrush是Qt框架中的一个类,它用于定义图形的填充模式。QBrush可以用于填充图形项(如QGraphicsItem)的形状,也可以用于绘制背景等。

关键特性

  • 颜色QBrush可以设置颜色,用于填充图形。
  • 样式QBrush可以设置样式,如实心、渐变、纹理等。
  • 纹理QBrush可以设置纹理,用于创建复杂的填充效果。

常用方法

  • QBrush(const QColor &color, Qt::BrushStyle style = Qt::SolidPattern):构造函数,可以指定颜色和样式。
  • void setColor(const QColor &color):设置颜色。
  • QColor color() const:获取颜色。
  • void setStyle(Qt::BrushStyle style):设置样式。
  • Qt::BrushStyle style() const:获取样式。
  • void setTexture(const QPixmap &pixmap):设置纹理。
  • QPixmap texture() const:获取纹理。

使用示例

以下是如何使用QBrush来填充一个矩形的示例:

QPainter painter(this);
QBrush brush(Qt::red); // 创建一个红色的刷子
brush.setStyle(Qt::SolidPattern); // 设置样式为实心
painter.setBrush(brush); // 设置画家的刷子
painter.drawRect(10, 10, 100, 100); // 绘制一个矩形

在这个示例中,我们首先创建了一个红色的QBrush对象,并设置了其样式为实心。然后,我们将这个刷子设置给了画家(QPainter),并使用画家绘制了一个矩形。结果是一个红色的实心矩形。

你还可以使用QBrush来创建更复杂的填充效果,如渐变、纹理等。例如,你可以使用QLinearGradientQRadialGradient来创建渐变效果,或者使用QPixmap来创建纹理效果。

<think>Qt 中的 MVC(Model-View-Controller)架构实际上演变为 Model/View 架构,其中 Controller 的功能由 View 和 Delegate 共同承担。在 Qt 中,MVC 模式被简化为 Model-View 架构,并引入了 Delegate(委托)来处理数据的显示和编辑。下面将详细解释并给出代码示例。 ### Qt MVC 详解 #### 核心组件 1. **Model(模型)**:负责管理数据,提供统一的接口供 View 和 Delegate 访问数据。所有模型都继承自 `QAbstractItemModel`。 2. **View(视图)**:负责显示模型中的数据,并提供用户交互界面。如 `QListView`、`QTableView`、`QTreeView`。 3. **Delegate(委托)**:负责渲染视图中的每个项(Item),并在编辑时提供编辑器(如文本框、复选框等)。委托继承自 `QAbstractItemDelegate` 或 `QStyledItemDelegate`。 #### 数据流 - 当模型数据改变时,模型会发出信号(如 `dataChanged`)通知视图更新。 - 当用户编辑数据时,委托将编辑后的数据通过模型提供的接口设置回模型。 #### 代码示例:自定义模型和委托 以下是一个使用自定义模型和委托的简单示例: ```cpp #include <QApplication> #include <QTableView> #include <QStandardItemModel> #include <QStyledItemDelegate> #include <QSpinBox> // 自定义委托,用于编辑整数范围 class SpinBoxDelegate : public QStyledItemDelegate { Q_OBJECT public: SpinBoxDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {} // 创建编辑器 QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override { QSpinBox *editor = new QSpinBox(parent); editor->setFrame(false); editor->setMinimum(0); editor->setMaximum(100); return editor; } // 设置编辑器数据 void setEditorData(QWidget *editor, const QModelIndex &index) const override { int value = index.model()->data(index, Qt::EditRole).toInt(); QSpinBox *spinBox = static_cast<QSpinBox*>(editor); spinBox->setValue(value); } // 设置模型数据 void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override { QSpinBox *spinBox = static_cast<QSpinBox*>(editor); spinBox->interpretText(); int value = spinBox->value(); model->setData(index, value, Qt::EditRole); } // 更新编辑器几何布局 void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override { editor->setGeometry(option.rect); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建模型 QStandardItemModel model(4, 2); for (int row = 0; row < 4; ++row) { for (int column = 0; column < 2; ++column) { QModelIndex index = model.index(row, column, QModelIndex()); model.setData(index, QVariant((row+1) * (column+1))); } } // 创建视图 QTableView tableView; tableView.setModel(&model); // 设置自定义委托 SpinBoxDelegate delegate; tableView.setItemDelegate(&delegate); tableView.setWindowTitle(QObject::tr("Spin Box Delegate")); tableView.show(); return app.exec(); } #include "main.moc" ``` #### 代码解释: 1. **自定义委托 `SpinBoxDelegate`**: - `createEditor`:创建一个 `QSpinBox` 作为编辑器。 - `setEditorData`:从模型中获取数据并设置到编辑器中。 - `setModelData`:将编辑器中的数据保存回模型。 - `updateEditorGeometry`:调整编辑器的大小和位置。 2. **模型**:使用 `QStandardItemModel`,这是一个通用的模型,可以存储表格数据。我们填充了一些初始数据。 3. **视图**:使用 `QTableView` 显示模型数据,并设置自定义委托。 #### 自定义模型示例 如果要创建自定义模型,需要继承 `QAbstractItemModel` 并实现以下方法: ```cpp class CustomModel : public QAbstractTableModel { Q_OBJECT public: int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; Qt::ItemFlags flags(const QModelIndex &index) const override; }; ``` #### 模型/视图的优点 - **分离数据与显示**:模型独立于视图,同一个模型可以被多个视图共享。 - **高效处理大数据**:视图只加载当前可见的数据,节省内存。 - **自定义显示和编辑**:通过委托可以灵活控制每个单元格的显示和编辑方式。 ### §§相关问题§§: 1. 如何实现一个基于 `QAbstractItemModel` 的自定义树形模型? 2. 在 Qt 的 Model/View 架构中,如何实现拖放操作? 3. 如何让一个模型同时被多个视图使用,并保持同步? 4. 在自定义委托中,如何根据不同的数据类型(如整数、字符串、日期)提供不同的编辑器?</think>### Qt MVC 架构详解 Qt 的 MVC(Model-View-Controller)实现称为 **Model/View 架构**,它将数据管理(Model)、数据展示(View)和用户交互(Delegate)解耦。以下是核心组件和实现细节: --- #### 一、核心组件关系图 ``` +----------------+ +---------------+ +-----------------+ | Model |<----->| View |<----->| Delegate | | (数据逻辑) | | (显示控件) | | (交互渲染器) | +----------------+ +---------------+ +-----------------+ | | | | 数据变更通知 | 用户操作转发 | 自定义绘制/编辑器 V V V +----------------+ +---------------+ +-----------------+ | QAbstractItemModel | QListView/QTableView | QStyledItemDelegate | | QStandardItemModel | QTreeView | 自定义Delegate | +----------------+ +---------------+ +-----------------+ ``` --- #### 二、Model 详解 **核心职责**:管理数据结构和数据访问 **关键类**:`QAbstractItemModel`(基类)、`QStandardItemModel`(通用模型) ```cpp // 创建自定义模型 class CustomModel : public QAbstractTableModel { Q_OBJECT public: int rowCount(const QModelIndex &parent = QModelIndex()) const override { return dataList.size(); } int columnCount(const QModelIndex &parent) const override { return 2; // ID 和 Name } QVariant data(const QModelIndex &index, int role) const override { if (!index.isValid()) return QVariant(); if (role == Qt::DisplayRole) { if (index.column() == 0) return dataList[index.row()].id; else return dataList[index.row()].name; } return QVariant(); } // 支持编辑 bool setData(const QModelIndex &index, const QVariant &value, int role) override { if (role == Qt::EditRole && index.isValid()) { if (index.column() == 1) { dataList[index.row()].name = value.toString(); emit dataChanged(index, index); // 关键:通知视图更新 return true; } } return false; } // 支持拖拽 Qt::ItemFlags flags(const QModelIndex &index) const override { return Qt::ItemIsEditable | Qt::ItemIsDragEnabled | QAbstractTableModel::flags(index); } private: struct ItemData { int id; QString name; }; QVector<ItemData> dataList; }; ``` --- #### 三、View 详解 **核心职责**:数据可视化与用户交互路由 **关键类**:`QListView`、`QTableView`、`QTreeView` ```cpp // 视图与模型绑定 QTableView *tableView = new QTableView; CustomModel *model = new CustomModel; tableView->setModel(model); // 关键绑定 // 视图配置 tableView->setSelectionMode(QAbstractItemView::ExtendedSelection); tableView->setDragDropMode(QAbstractItemView::DragDrop); // 连接视图信号 connect(tableView, &QTableView::doubleClicked, [](const QModelIndex &index){ qDebug() << "双击行:" << index.row(); }); ``` --- #### 四、Delegate 详解 **核心职责**:控制数据渲染和编辑行为 **关键类**:`QStyledItemDelegate`(基类) ```cpp // 自定义委托:在第二列显示进度条 class ProgressBarDelegate : public QStyledItemDelegate { public: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { if (index.column() == 1) { int progress = index.data().toInt(); QStyleOptionProgressBar progressBarOption; progressBarOption.rect = option.rect; progressBarOption.minimum = 0; progressBarOption.maximum = 100; progressBarOption.progress = progress; progressBarOption.text = QString::number(progress) + "%"; progressBarOption.textVisible = true; QApplication::style()->drawControl( QStyle::CE_ProgressBar, &progressBarOption, painter ); } else { QStyledItemDelegate::paint(painter, option, index); } } // 创建编辑器(当用户编辑时) QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override { if (index.column() == 1) { QSpinBox *editor = new QSpinBox(parent); editor->setRange(0, 100); return editor; } return QStyledItemDelegate::createEditor(parent, option, index); } }; // 使用委托 tableView->setItemDelegateForColumn(1, new ProgressBarDelegate); ``` --- #### 五、完整工作流程示例 ```cpp int main(int argc, char *argv[]) { QApplication app(argc, argv); // 1. 创建模型 QStandardItemModel model(4, 2); for (int row = 0; row < 4; ++row) { model.setItem(row, 0, new QStandardItem(QString("ID-%1").arg(row+1))); model.setItem(row, 1, new QStandardItem(QString::number((row+1)*25))); } // 2. 创建视图 QTableView tableView; tableView.setModel(&model); // 3. 设置委托 tableView.setItemDelegateForColumn(1, new ProgressBarDelegate); // 4. 显示 tableView.show(); return app.exec(); } ``` --- #### 六、高级特性 1. **代理模型**(Proxy Models) ```cpp // 排序过滤代理 QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel; proxyModel->setSourceModel(sourceModel); tableView->setModel(proxyModel); // 自定义过滤 proxyModel->setFilterKeyColumn(1); // 按第二列过滤 proxyModel->setFilterRegularExpression(QRegularExpression("^A.*")); ``` 2. **角色系统**(Data Roles) ```cpp // 在模型中定义 QVariant data(const QModelIndex &index, int role) const override { if (role == Qt::BackgroundRole && index.column() == 0) return QBrush(Qt::yellow); if (role == CustomRoles::DataTypeRole) return "ProgressData"; } // 在委托中使用 void paint(...) { QString type = index.data(CustomRoles::DataTypeRole).toString(); // ... } ``` 3. **拖放支持** ```cpp // 在模型中实现 Qt::DropActions supportedDropActions() const override { return Qt::CopyAction | Qt::MoveAction; } bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override { // 处理拖放数据 } ``` --- ### 七、性能优化技巧 1. **批量更新**: ```cpp model->beginResetModel(); // 大规模数据修改 model->endResetModel(); ``` 2. **按需加载**: ```cpp // 在模型中实现 bool canFetchMore(const QModelIndex &parent) const override; void fetchMore(const QModelIndex &parent) override; ``` 3. **模型测试**: ```cpp QAbstractItemModelTester tester(&model); ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值