Qt模型视图中的委托
文章目錄
- 1 初探QT模型視圖中的委托
- 2 自定義委托
- 3 深度解析視圖與委托
- 3.1 實例1:自定義視圖顯示方式
- 3.2 實例2:自定義視圖顯示方式提升用戶體驗
1 初探QT模型視圖中的委托
首先來看一個問題:模型負責組織數據,視圖負責顯示數據,如何編輯數據呢?
我們先來看一下傳統的MVC設計模式:
Qt中的模型視圖設計模型如何處理用戶輸入呢?
- 視圖中集成了處理用戶輸入的功能。
- 視圖將用戶輸入作為內部獨立的子功能而實現。
模型視圖中的委托:
- 委托(Delegate)是視圖中處理用戶輸入的部件。
- 視圖可以設置委托對象用于處理用戶輸入。
- 委托對象負責創建和顯示用戶輸入上下文。
- 如:編輯框的創建和顯示。
- 如:編輯框的創建和顯示。
委托中的編輯器:
- 委托能夠提供編輯時需要的上下文環境(編輯器)。
- 不同委托提供的編輯器類型不同(文本框、單選框,等)。
- 編輯器從模型獲取數據,并將編輯結果返回模型。
委托中的關鍵函數:
- createEditor:需要編輯數據時,創建編輯器組件。
- updateEditorGeometry:更新編輯器組件的大小。
- setEditorData:通過索引從模型中獲取數據。
- setModelData:將編輯后的新數據返回模型。
委托中的關鍵信號:
- void closeEditor(QWidget* editor):編輯器組件關閉信號。
- void commitData(QWidget* editor):新數據提交信號。
對模型中的委托進行一下簡單的總結:
- 委托是視圖中處理用戶輸入的部件。
- 視圖可以設置委托對象用于處理用戶輸入。
- 委托能夠提供編輯時需要的上下文環境(編輯器)。
- 不同委托提供的編輯器類型不同(文本框、單選框等)。
- 編輯器從模型中獲取數據,并將編輯結果返回模型。
如下為測試代碼:
SubStyledItemDelegate.h:
#ifndef SUBSTYLEDITEMDELEGATE_H #define SUBSTYLEDITEMDELEGATE_H#include <QStyledItemDelegate>class SubStyledItemDelegate : public QStyledItemDelegate {Q_OBJECT protected slots:void onCloseEditor(QWidget* editor);void onCommitData(QWidget* editor); public:explicit SubStyledItemDelegate(QObject* parent = 0);QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;void setEditorData(QWidget *editor, const QModelIndex &index) const;void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; };#endif // SUBSTYLEDITEMDELEGATE_HSubStyledItemDelegate.cpp:
#include "SubStyledItemDelegate.h" #include <QDebug>SubStyledItemDelegate::SubStyledItemDelegate(QObject *parent) :QStyledItemDelegate(parent) {connect(this, SIGNAL(closeEditor(QWidget*)), this, SLOT(onCloseEditor(QWidget*)));connect(this, SIGNAL(commitData(QWidget*)), this, SLOT(onCommitData(QWidget*))); }QWidget* SubStyledItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {qDebug() << "SubStyledItemDelegate::createEditor";return QStyledItemDelegate::createEditor(parent, option, index); }void SubStyledItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {qDebug() << "SubStyledItemDelegate::updateEditorGeometry";QStyledItemDelegate::updateEditorGeometry(editor, option, index); }void SubStyledItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {qDebug() << "SubStyledItemDelegate::setEditorData";QStyledItemDelegate::setEditorData(editor, index); }void SubStyledItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {qDebug() << "SubStyledItemDelegate::setModelData";return QStyledItemDelegate::setModelData(editor, model, index); }void SubStyledItemDelegate::onCloseEditor(QWidget* editor) {qDebug() << "SubStyledItemDelegate::onCloseEditor"; }void SubStyledItemDelegate::onCommitData(QWidget* editor) {qDebug() << "SubStyledItemDelegate::onCommitData"; }Widget.h:
#ifndef WIDGET_H #define WIDGET_H#include <QtGui/QWidget> #include <QTableView> #include <QStandardItemModel> #include <QPushButton> #include "SubStyledItemDelegate.h"class Widget : public QWidget {Q_OBJECTQTableView m_view;QStandardItemModel m_model;QPushButton m_testBtn;SubStyledItemDelegate m_delegate;void initView();void initModel();private slots:void onTestBtnClicked(); public:Widget(QWidget* parent = 0);~Widget(); };#endif // WIDGET_HWidget.cpp:
#include "Widget.h" #include <QModelIndex> #include <QDebug>Widget::Widget(QWidget* parent) : QWidget(parent) {initView();initModel();m_view.setModel(&m_model);m_testBtn.setParent(this);m_testBtn.move(10, 120);m_testBtn.resize(300, 30);m_testBtn.setText("Test");connect(&m_testBtn, SIGNAL(clicked()), this, SLOT(onTestBtnClicked())); }void Widget::initView() {m_view.setParent(this);m_view.move(10, 10);m_view.resize(300, 100);m_view.setItemDelegate(&m_delegate); }void Widget::initModel() {QStandardItem* root = m_model.invisibleRootItem();QStandardItem* itemA = new QStandardItem();QStandardItem* itemB = new QStandardItem();QStandardItem* itemC = new QStandardItem();QStandardItem* itemD = new QStandardItem();itemA->setData("A", Qt::DisplayRole);itemB->setData("B", Qt::DisplayRole);itemC->setData("C", Qt::DisplayRole);itemD->setData("D", Qt::DisplayRole);root->setChild(0, 0, itemA);root->setChild(0, 1, itemB);root->setChild(1, 0, itemC);root->setChild(1, 1, itemD); }void Widget::onTestBtnClicked() {qDebug() << "Model Data:";for(int i=0; i<m_model.rowCount(); i++){qDebug() << "Row: " << i;for(int j=0; j<m_model.columnCount(); j++){QModelIndex index = m_model.index(i, j, QModelIndex());QString text = index.data(Qt::DisplayRole).toString();qDebug() << text;}qDebug() << endl;}qDebug() << "Current View Delegate: " << m_view.itemDelegate(); }Widget::~Widget() {}main.cpp:
#include <QtGui/QApplication> #include "Widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }一次完成的修改數據的流程輸入結果如下:
當結束輸入時才觸發commitData。
2 自定義委托
首先來看一下委托的本質:
- 為視圖提供數據編輯的上下文環境。
- 產生界面元素的工廠類。
- 能夠使用和設置模型中的數據。
問題:如何自定一個委托類?
自定義委托時需要重寫的函數:
思考一下:自定義委托時重寫的函數由誰調用?視圖調用。
對自定義委托類總結一下:
- 自定義委托類時需要重寫相應的成員函數。
- 根據需要創建編輯組件并設置組件中的數據。
- 編輯結束后將數據返回模型。
- 成員函數的參數攜帶了數據存取時需要的信息。
如下為自定義委托類的代碼:
CustomizedItemDelegate.h:
#ifndef CUSTOMIZEDITEMDELEGATE_H #define CUSTOMIZEDITEMDELEGATE_H#include <QItemDelegate> #include <QModelIndex>class CustomizedItemDelegate : public QItemDelegate {Q_OBJECTmutable QModelIndex m_index; protected slots:void onCloseEditor(QWidget*); public:explicit CustomizedItemDelegate(QObject *parent = 0);QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;void setEditorData(QWidget *editor, const QModelIndex &index) const;void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; };#endif // CUSTOMIZEDITEMDELEGATE_HCustomizedItemDelegate.cpp:
#include "CustomizedItemDelegate.h" #include <QCheckBox> #include <QComboBox>CustomizedItemDelegate::CustomizedItemDelegate(QObject *parent) :QItemDelegate(parent) {connect(this, SIGNAL(closeEditor(QWidget*)), this, SLOT(onCloseEditor(QWidget*))); }QWidget* CustomizedItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {QWidget* ret = NULL;m_index = index;if( index.data().type() == QVariant::Bool ){QCheckBox* cb = new QCheckBox(parent);cb->setText("Check to TRUE");ret = cb;}else if( index.data().type() == QVariant::Char ){QComboBox* cb = new QComboBox(parent);cb->addItem("A");cb->addItem("B");cb->addItem("C");cb->addItem("D");ret = cb;}else{ret = QItemDelegate::createEditor(parent, option, index);}return ret; }void CustomizedItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {editor->setGeometry(option.rect); }void CustomizedItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {if( index.data().type() == QVariant::Bool ){QCheckBox* cb = dynamic_cast<QCheckBox*>(editor);if( cb != NULL ){cb->setChecked(index.data().toBool());}}else if( index.data().type() == QVariant::Char ){QComboBox* cb = dynamic_cast<QComboBox*>(editor);if( cb != NULL ){for(int i=0; i<cb->count(); i++){if( cb->itemText(i) == index.data().toString() ){cb->setCurrentIndex(i);break;}}}}else{QItemDelegate::setEditorData(editor, index);} }void CustomizedItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {if( index.data().type() == QVariant::Bool ){QCheckBox* cb = dynamic_cast<QCheckBox*>(editor);if( cb != NULL ){model->setData(index, cb->isChecked(), Qt::DisplayRole);}}else if( index.data().type() == QVariant::Char ){QComboBox* cb = dynamic_cast<QComboBox*>(editor);if( cb != NULL ){model->setData(index, cb->currentText().at(0), Qt::DisplayRole);}}else{QItemDelegate::setModelData(editor, model, index);} }void CustomizedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {if( m_index != index ){QItemDelegate::paint(painter, option, index);} }void CustomizedItemDelegate::onCloseEditor(QWidget*) {m_index = QModelIndex(); }Widget.h:
#ifndef WIDGET_H #define WIDGET_H#include <QtGui/QWidget> #include <QTableView> #include <QStandardItemModel> #include <QPushButton> #include "CustomizedItemDelegate.h"class Widget : public QWidget {Q_OBJECTQTableView m_view;QStandardItemModel m_model;CustomizedItemDelegate m_delegate;void initView();void initModel();public:Widget(QWidget* parent = 0);~Widget(); };#endif // WIDGET_HWidget.cpp:
#include "Widget.h" #include <QStandardItem> #include <QModelIndex> #include <QStringList> #include <QDebug>Widget::Widget(QWidget* parent) : QWidget(parent) {initView();initModel();m_view.setModel(&m_model);for(int i=0; i<m_model.columnCount(); i++){m_view.setColumnWidth(i, 125);} }void Widget::initView() {m_view.setParent(this);m_view.move(10, 10);m_view.resize(500, 200);m_view.setItemDelegate(&m_delegate); }void Widget::initModel() {QStandardItem* root = m_model.invisibleRootItem();QStringList hl;QStandardItem* itemA1 = new QStandardItem();QStandardItem* itemB1 = new QStandardItem();QStandardItem* itemC1 = new QStandardItem();QStandardItem* itemA2 = new QStandardItem();QStandardItem* itemB2 = new QStandardItem();QStandardItem* itemC2 = new QStandardItem();hl.append("Language");hl.append("Level");hl.append("Script");m_model.setHorizontalHeaderLabels(hl);itemA1->setData("Delphi", Qt::DisplayRole);itemB1->setData(QChar('A'), Qt::DisplayRole);itemC1->setData(false, Qt::DisplayRole);itemA2->setData("Perl", Qt::DisplayRole);itemB2->setData(QChar('B'), Qt::DisplayRole);itemC2->setData(true, Qt::DisplayRole);root->setChild(0, 0, itemA1);root->setChild(0, 1, itemB1);root->setChild(0, 2, itemC1);root->setChild(1, 0, itemA2);root->setChild(1, 1, itemB2);root->setChild(1, 2, itemC2); }Widget::~Widget() {}main.cpp:
#include <QtGui/QApplication> #include "Widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }3 深度解析視圖與委托
深度的思考:委托是視圖的構成部分,那么委托是否幫助視圖顯示具體數據呢?
分析:Qt中的委托作為視圖的內部組件而存在,因此,委托是視圖的一部分。必然,委托需要承擔數據顯示的部分工作。
關于視圖和委托:
- 視圖負責確定數據項的組織顯示方式(列表、樹形、表格)。
- 委托負責具體數據項的顯示和編輯(數據值、編輯器)。
- 視圖和委托共同完成數據顯示功能和數據編輯功能。
- 重寫委托的paint函數自定義數據項顯示方式。
- 重寫委托的editorEvent函數處理交互事件。
3.1 實例1:自定義視圖顯示方式
思考:如何改變視圖默認的數據顯示方式?
自定義委托的默認數據顯示方式:
在paint中自定義數據顯示方式:
在editorEvent中處理交互事件:
CustomizedItemDelegate.h:
CustomizedItemDelegate.cpp:
#include "CustomizedItemDelegate.h" #include <QComboBox> #include <QMouseEvent> #include <QApplication> #include <QDebug>CustomizedItemDelegate::CustomizedItemDelegate(QObject *parent) :QItemDelegate(parent) {}QWidget* CustomizedItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {QWidget* ret = NULL;if( index.data().type() == QVariant::Char ){QComboBox* cb = new QComboBox(parent);cb->addItem("A");cb->addItem("B");cb->addItem("C");cb->addItem("D");ret = cb;}else{ret = QItemDelegate::createEditor(parent, option, index);}return ret; }void CustomizedItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {editor->setGeometry(option.rect); }void CustomizedItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {if( index.data().type() == QVariant::Char ){QComboBox* cb = dynamic_cast<QComboBox*>(editor);if( cb != NULL ){for(int i=0; i<cb->count(); i++){if( cb->itemText(i) == index.data().toString() ){cb->setCurrentIndex(i);break;}}}}else{QItemDelegate::setEditorData(editor, index);} }void CustomizedItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {if( index.data().type() == QVariant::Char ){QComboBox* cb = dynamic_cast<QComboBox*>(editor);if( cb != NULL ){model->setData(index, cb->currentText().at(0), Qt::DisplayRole);}}else{QItemDelegate::setModelData(editor, model, index);} }void CustomizedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {if( index.data().type() == QVariant::Bool ){bool data = index.data(Qt::DisplayRole).toBool();QStyleOptionButton checkBoxStyle;checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off;checkBoxStyle.state |= QStyle::State_Enabled;checkBoxStyle.rect = option.rect;checkBoxStyle.rect.setX(option.rect.x() + option.rect.width() / 2 - 6);QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxStyle, painter);}else{QItemDelegate::paint(painter, option, index);} }bool CustomizedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) {bool ret = true;if( index.data().type() == QVariant::Bool ){QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(event);if( (event->type() == QEvent::MouseButtonPress) && option.rect.contains(mouseEvent->pos()) ){bool data = index.data(Qt::DisplayRole).toBool();qDebug() << "set model data: " << !data;qDebug() << model->setData(index, !data, Qt::DisplayRole);}}else{ret = QItemDelegate::editorEvent(event, model, option, index);}return ret; }Widget.h:
#ifndef WIDGET_H #define WIDGET_H#include <QtGui/QWidget> #include <QTableView> #include <QStandardItemModel> #include "CustomizedItemDelegate.h"class Widget : public QWidget {Q_OBJECTQTableView m_view;QStandardItemModel m_model;CustomizedItemDelegate m_delegate;void initView();void initModel();public:Widget(QWidget* parent = 0);~Widget(); };#endif // WIDGET_HWidget.cpp:
#include "Widget.h" #include <QStandardItem> #include <QModelIndex> #include <QStringList> #include <QDebug>Widget::Widget(QWidget* parent) : QWidget(parent) {initView();initModel();m_view.setModel(&m_model);for(int i=0; i<m_model.columnCount(); i++){m_view.setColumnWidth(i, 125);} }void Widget::initView() {m_view.setParent(this);m_view.move(10, 10);m_view.resize(500, 200);m_view.setItemDelegate(&m_delegate); }void Widget::initModel() {QStandardItem* root = m_model.invisibleRootItem();QStringList hl;QStandardItem* itemA1 = new QStandardItem();QStandardItem* itemB1 = new QStandardItem();QStandardItem* itemC1 = new QStandardItem();QStandardItem* itemA2 = new QStandardItem();QStandardItem* itemB2 = new QStandardItem();QStandardItem* itemC2 = new QStandardItem();hl.append("Language");hl.append("Level");hl.append("Script");m_model.setHorizontalHeaderLabels(hl);itemA1->setData("Delphi", Qt::DisplayRole);itemB1->setData(QChar('A'), Qt::DisplayRole);itemC1->setData(false, Qt::DisplayRole);itemA2->setData("Perl", Qt::DisplayRole);itemB2->setData(QChar('B'), Qt::DisplayRole);itemC2->setData(true, Qt::DisplayRole);root->setChild(0, 0, itemA1);root->setChild(0, 1, itemB1);root->setChild(0, 2, itemC1);root->setChild(1, 0, itemA2);root->setChild(1, 1, itemB2);root->setChild(1, 2, itemC2); }Widget::~Widget() {}main.cpp:
#include <QtGui/QApplication> #include "Widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }3.2 實例2:自定義視圖顯示方式提升用戶體驗
下面看一個實例的分析與改進:
考慮一下:如何改進程序界面使其擁有更好的用戶體驗?
改進思路:將Progress從純文本的顯示方式改變為進度條+文本顯示的方式;可以直觀的讓用戶感受到當前的任務進度。
解決方案:
在paint成員函數中繪制進度條顯示:
在editorEvent成員函數中禁止數據編輯操作:
任務進度模擬:
實例擴展:在實際工程項目中,可以使用后臺線程根據實際的任務情況更新模型中的數據,從而更新數據的界面顯示。
總結一下自定義視圖數據顯示的方法:
實例代碼如下:
CustomizedItemDelegate.h:
#ifndef CUSTOMIZEDITEMDELEGATE_H #define CUSTOMIZEDITEMDELEGATE_H#include <QItemDelegate>class CustomizedItemDelegate : public QItemDelegate {Q_OBJECT public:explicit CustomizedItemDelegate(QObject *parent = 0);void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); };#endif // CUSTOMIZEDITEMDELEGATE_HCustomizedItemDelegate.cpp:
#include "CustomizedItemDelegate.h" #include <QApplication> #include <QEvent>CustomizedItemDelegate::CustomizedItemDelegate(QObject *parent) :QItemDelegate(parent) { }void CustomizedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {if( index.data().type() == QVariant::Int ){const int DELTA = 4;int progress = index.data().toInt();QStyleOptionProgressBar progressBarOption;int top = option.rect.top() + DELTA;int left = option.rect.left() + DELTA;int width = option.rect.width() - 2 * DELTA;int height = option.rect.height() - 2 * DELTA;progressBarOption.rect = QRect(left, top, width, height);progressBarOption.minimum = 0;progressBarOption.maximum = 100;progressBarOption.progress = progress;progressBarOption.textVisible = true;progressBarOption.text = QString().sprintf("%d", progress) + "%";progressBarOption.textAlignment = Qt::AlignCenter;QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);}else{QItemDelegate::paint(painter, option, index);} }bool CustomizedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) {bool ret = true;if( event->type() != QEvent::MouseButtonDblClick ){ret = QItemDelegate::editorEvent(event, model, option, index);}return ret; }Widget.h:
#ifndef WIDGET_H #define WIDGET_H#include <QtGui/QWidget> #include <QTableView> #include <QStandardItemModel> #include <QTimer> #include "CustomizedItemDelegate.h"class Widget : public QWidget {Q_OBJECTQTableView m_view;QStandardItemModel m_model;CustomizedItemDelegate m_delegate;QTimer m_timer;void initView();void initModel(); private slots:void timerTimeout(); public:Widget(QWidget* parent = 0);~Widget(); };#endif // WIDGET_HWidget.cpp:
#include "Widget.h" #include <QStandardItem> #include <QModelIndex> #include <QStringList> #include <QModelIndex> #include <QDebug>Widget::Widget(QWidget* parent) : QWidget(parent) {initView();initModel();m_view.setModel(&m_model);for(int i=0; i<m_model.columnCount(); i++){m_view.setColumnWidth(i, 200);}connect(&m_timer, SIGNAL(timeout()), this, SLOT(timerTimeout()));m_timer.setParent(this);m_timer.start(500); }void Widget::initView() {m_view.setParent(this);m_view.move(10, 10);m_view.resize(500, 200);m_view.setItemDelegate(&m_delegate); }void Widget::initModel() {QStandardItem* root = m_model.invisibleRootItem();QStringList hl;QStandardItem* itemA1 = new QStandardItem();QStandardItem* itemB1 = new QStandardItem();QStandardItem* itemA2 = new QStandardItem();QStandardItem* itemB2 = new QStandardItem();hl.append("Task");hl.append("Progress");m_model.setHorizontalHeaderLabels(hl);itemA1->setData("Delphi", Qt::DisplayRole);itemB1->setData(70, Qt::DisplayRole);itemA2->setData("Perl", Qt::DisplayRole);itemB2->setData(60, Qt::DisplayRole);root->setChild(0, 0, itemA1);root->setChild(0, 1, itemB1);root->setChild(1, 0, itemA2);root->setChild(1, 1, itemB2); }void Widget::timerTimeout() {QModelIndex i1 = m_model.index(0, 1, QModelIndex());QModelIndex i2 = m_model.index(1, 1, QModelIndex());QVariant v1 = (i1.data().toInt() + 1) % 100;QVariant v2 = (i2.data().toInt() + 3) % 100;m_model.setData(i1, v1, Qt::DisplayRole);m_model.setData(i2, v2, Qt::DisplayRole); }Widget::~Widget() {}main.cpp:
#include <QtGui/QApplication> #include "Widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }參考資料:
總結
以上是生活随笔為你收集整理的Qt模型视图中的委托的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 场内基金和场外基金的区别
- 下一篇: 广发银行信用卡如何注销