文章目录
- 一、Qt MVD概念讲解
- 二、Qt模型视图代理之:QTableView的使用
- 三、Qt模型视图代理之:QListView的使用
一、Qt MVD概念讲解
Qt MVD(Model-View-Delegate)是Qt框架中的一种设计模式,是Qt中用界面组件显示与编辑数据的一种结构。视图(view)是显示和编辑数据的界面组件,模型(Model)是视图与原始数据之间的接口。Model/View 结构的典型应用是在数据库应用程序中,例如数据库中的一个数据表可以在一个QTableView组件中显示和编辑。
MVD三个组件的介绍:
-
模型
模型 (Model) 是视图与原始数据之间的接口。原始数据可以是数据库中的一个数据表、内存中的一个StringList、磁盘文件结构等。QAbstractItemModel 是所有模型的祖宗类,其它 model 类都派生于它
-
视图
视图(view)是显示和编辑数据的界面组件。它不直接与数据交互,而是通过模型提供的接口来获取数据。Qt提供了多种视图类,如
QListView
、QTableView
和QTreeView
等,QListWidget、QTreeWidget 和 QTableWidget 是视图类的简化版,它们不使用数据模型,而是将数据直接存储在组件的每个项里面。 -
代理
代理 (Delegate) 为视图组件提供数据编辑器,如在表格组件中,编辑一个单元格的数据时,缺省是使用一个 QLineEdit 编辑框,代理负责从数据模型获取相应的数据,然后显示在编辑器里,修改数据后,又将其保存到数据模型中
- QAbstractItemDelegate Class是所有代理类的抽象基类
- QStyledItemDelegate Class是视图组件使用的缺省的代理类
如何实现自定义代理?
自定义代理组件,主要用于自定义编辑器组件的行为,都必须实现如下的4个函数:
-
createEditor函数用于创建编辑特定数据模型项的编辑器组件。,如一个QSpinBox组件或一个QComboBox组件。
如果数据模型包含不同类型的数据,需要根据数据类型来创建不同类型的编辑器组件
-
setEditorData函数用于将数据模型中的数据显示在编辑器组件中。它从数据模型中检索数据,并将其设置到编辑器组件。
-
setModelData函数用于将编辑器组件中的更改提交回数据模型。它从编辑器组件获取数据,并更新数据模型。
-
updateEditorGeometry函数用于调整编辑器组件的大小和位置,以确保它适合其所在的视图项
在视图组件中设置自定义代理,需要调用setItemDelegateForColumn函数
ui->tableView->setItemDelegateForColumn(3, &m_floatSpinDelegate); ui->tableView->setItemDelegateForColumn(4, &m_intSpinDelegate); ui->tableView->setItemDelegateForColumn(5, &m_comboBoxDelegate);
二、Qt模型视图代理之:QTableView的使用
QTableView用于显示和编辑表格数据。下面案例需要用到自定义代理组件
示例:
自定义下拉列表代理组件
CComboBoxDelegate.h:
#ifndef CCOMBOBOXDELEGATE_H
#define CCOMBOBOXDELEGATE_H#include <QItemDelegate>class CComboBoxDelegate : public QItemDelegate
{Q_OBJECTpublic:CComboBoxDelegate(QObject *parent=0);//自定义代理组件必须继承以下4个函数QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const Q_DECL_OVERRIDE;void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;
};#endif // CCOMBOBOXDELEGATE_H
CComboBoxDelegate.cpp:
#include "ccomboboxdelegate.h"
#include <QComboBox>CComboBoxDelegate::CComboBoxDelegate(QObject *parent):QItemDelegate(parent)
{}QWidget *CComboBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
{QComboBox *editor = new QComboBox(parent);editor->addItem(u8"优");editor->addItem(u8"良");editor->addItem(u8"一般");return editor;
}void CComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{QString str = index.model()->data(index, Qt::EditRole).toString();QComboBox *comboBox = static_cast<QComboBox*>(editor);comboBox->setCurrentText(str);
}void CComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{QComboBox *comboBox = static_cast<QComboBox*>(editor);QString str = comboBox->currentText();model->setData(index, str, Qt::EditRole);
}void CComboBoxDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const
{editor->setGeometry(option.rect);
}
自定义上下箭头输入框代理组件
CFloatSpinDelegate.h:
#ifndef CFLOATSPINDELEGATE_H
#define CFLOATSPINDELEGATE_H#include <QObject>
#include <QWidget>
#include <QStyledItemDelegate>class CFloatSpinDelegate : public QStyledItemDelegate
{Q_OBJECT
public:CFloatSpinDelegate(QObject *parent=0);//自定义代理组件必须继承以下4个函数//创建编辑组件QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const Q_DECL_OVERRIDE;void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;
};#endif // CFLOATSPINDELEGATE_H
CFloatSpinDelegate.cpp:
#include "cfloatspindelegate.h"
#include <QDoubleSpinBox>CFloatSpinDelegate::CFloatSpinDelegate(QObject *parent):QStyledItemDelegate(parent)
{}QWidget *CFloatSpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
{Q_UNUSED(option);Q_UNUSED(index);QDoubleSpinBox *editor = new QDoubleSpinBox(parent);editor->setFrame(false);editor->setMinimum(0);editor->setDecimals(2);editor->setMaximum(100);return editor;
}void CFloatSpinDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{float value = index.model()->data(index, Qt::EditRole).toFloat();QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);spinBox->setValue(value);
}void CFloatSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{QDoubleSpinBox *spinBox = static_cast<QDoubleSpinBox*>(editor);spinBox->interpretText();float value = spinBox->value();QString str=QString::asprintf("%.2f",value);model->setData(index, str, Qt::EditRole);
}void CFloatSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{editor->setGeometry(option.rect);
}
CIntSpinDelegate.h:
#ifndef CINTSPINDELEGATE_H
#define CINTSPINDELEGATE_H#include <QStyledItemDelegate>class CIntSpinDelegate : public QStyledItemDelegate
{Q_OBJECT
public:CIntSpinDelegate(QObject *parent=0);//自定义代理组件必须继承以下4个函数//创建编辑组件QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;//从数据模型获取数据,显示到代理组件中void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;//将代理组件的数据,保存到数据模型中void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const Q_DECL_OVERRIDE;//更新代理编辑组件的大小void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,const QModelIndex &index) const Q_DECL_OVERRIDE;
};#endif // CINTSPINDELEGATE_H
CIntSpinDelegate.cpp:
#include "cintspindelegate.h"
#include <QSpinBox>CIntSpinDelegate::CIntSpinDelegate(QObject *parent):QStyledItemDelegate(parent)
{}QWidget *CIntSpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option, const QModelIndex &index) const
{//创建代理编辑组件Q_UNUSED(option);Q_UNUSED(index);QSpinBox *editor = new QSpinBox(parent); //创建一个QSpinBoxeditor->setFrame(false); //设置为无边框editor->setMinimum(0);editor->setMaximum(120);return editor; //返回此编辑器
}void CIntSpinDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{//从数据模型获取数据,显示到代理组件中//获取数据模型的模型索引指向的单元的数据int value = index.model()->data(index, Qt::EditRole).toInt();QSpinBox *spinBox = static_cast<QSpinBox*>(editor); //强制类型转换spinBox->setValue(value); //设置编辑器的数值
}void CIntSpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{//将代理组件的数据,保存到数据模型中QSpinBox *spinBox = static_cast<QSpinBox*>(editor); //强制类型转换spinBox->interpretText(); //解释数据,如果数据被修改后,就触发信号int value = spinBox->value(); //获取spinBox的值model->setData(index, value, Qt::EditRole); //更新到数据模型
}void CIntSpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{//设置组件大小Q_UNUSED(index);editor->setGeometry(option.rect);
}
设置数据模型、选择模型与设置自定义代理组件;使用了QAxObject
打开Excel(windows上)来添加数据
widget.h:
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QStandardItemModel>
#include <QItemSelectionModel>
#include "cintspindelegate.h"
#include "cfloatspindelegate.h"
#include "ccomboboxdelegate.h"QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_btnOpenExcel_clicked();void on_btnReshowData_clicked();void OnCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous);void on_btnAppendLast_clicked();void on_btnAppend_clicked();void on_btnDeleteSelectedLine_clicked();private:Ui::Widget *ui;QStandardItemModel *m_pItemModel;//数据模型QItemSelectionModel *m_pSelectionModel;//Item选择模型CIntSpinDelegate m_intSpinDelegate; //整型数spinbox代理CFloatSpinDelegate m_floatSpinDelegate; //浮点数spinbox代理CComboBoxDelegate m_comboBoxDelegate; //combobox代理
};
#endif // WIDGET_H
widget.cpp:
#include "widget.h"
#include "ui_widget.h"
#include <QAxObject>
#include <QFileDialog>
#include <QStandardPaths>static const int COLUMN_COUNT = 7;Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);showMaximized();m_pItemModel = new QStandardItemModel(1,COLUMN_COUNT,this);m_pSelectionModel = new QItemSelectionModel(m_pItemModel); //Item选择模型//选择当前单元格变化时的信号与槽connect(m_pSelectionModel, &QItemSelectionModel::currentChanged, this, &Widget::OnCurrentChanged);ui->tableView->setModel(m_pItemModel); //设置数据模型到表格视图ui->tableView->setSelectionModel(m_pSelectionModel); //设置选择模型到表格视图ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection); //设置选择模式为扩展选择,允许用户进行多选ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems); //设置选择行为为选择条目//给第3,4,5列设置自定义代理组件ui->tableView->setItemDelegateForColumn(3, &m_floatSpinDelegate);ui->tableView->setItemDelegateForColumn(4, &m_intSpinDelegate);ui->tableView->setItemDelegateForColumn(5, &m_comboBoxDelegate);
}Widget::~Widget()
{delete ui;
}//打开excel
void Widget::on_btnOpenExcel_clicked()
{QAxObject *excel = new QAxObject(this);excel->setControl("Excel.Application");excel->setProperty("Visible", false); //显示窗体看效果,选择ture将会看到excel表格被打开excel->setProperty("DisplayAlerts", true);QAxObject *workbooks = excel->querySubObject("WorkBooks"); //获取工作簿(excel文件)集合QString str = QFileDialog::getOpenFileName(this, u8"打开excel","D:/MyQtCreatorProject/9_2_tableView",u8"Excel 文件(*.xls *.xlsx)");//打开刚才选定的excelworkbooks->dynamicCall("Open(const QString&)", str);QAxObject *workbook = excel->querySubObject("ActiveWorkBook");QAxObject *worksheet = workbook->querySubObject("WorkSheets(int)",1);QAxObject *usedRange = worksheet->querySubObject("UsedRange"); //获取表格中的数据范围QVariant var = usedRange->dynamicCall("Value"); //将所有的数据读取刀QVariant容器中保存QList<QList<QVariant>> excel_list; //用于将QVariant转换为Qlist的二维数组QVariantList varRows=var.toList();if(varRows.isEmpty()){return;}const int row_count = varRows.size();QVariantList rowData;for(int i=0;i<row_count;++i){rowData = varRows[i].toList();excel_list.push_back(rowData);}//将每一行的内容放到contentListQList<QStringList> contentList;for(int i = 0; i<row_count; i++){QList<QVariant> curList = excel_list.at(i);int curRowCount = curList.size();QStringList oneLineStrlist;for(int j = 0; j < curRowCount; j++){QString content = curList.at(j).toString();oneLineStrlist << content;}contentList << oneLineStrlist;}workbook->dynamicCall( "Close(Boolean)", false );excel->dynamicCall( "Quit(void)" );delete excel;//解析contentList,填充tableViewint rowCounts = contentList.size();QStandardItem *aItem;//遍历行for(int i = 0; i < rowCounts; i++){QStringList tmpList=contentList[i];if(i == 0){//设置表头m_pItemModel->setHorizontalHeaderLabels(tmpList);}else{int j;for (j = 0; j < COLUMN_COUNT-1; j++){//不包含最后一列aItem=new QStandardItem(tmpList.at(j));m_pItemModel->setItem(i-1,j,aItem); //为模型的某个行列位置设置Item}//设置最后一列aItem=new QStandardItem(contentList[0].at(j)); //获取最后一列的指针aItem->setCheckable(true); //设置可以使用check控件if (tmpList.at(j)=="0")aItem->setCheckState(Qt::Unchecked); //根据数据设置check状态elseaItem->setCheckState(Qt::Checked);m_pItemModel->setItem(i-1 , j, aItem); //设置最后一列}}
}//选择单元格变化时的响应
void Widget::OnCurrentChanged(const QModelIndex ¤t, const QModelIndex &previous)
{Q_UNUSED(previous);if (current.isValid()) //当前模型索引有效{ui->textEdit->clear();ui->textEdit->append(QString::asprintf(u8"当前单元格:%d行,%d列",current.row(),current.column())); //显示模型索引的行和列号QStandardItem *aItem;aItem = m_pItemModel->itemFromIndex(current); //从模型索引获得Itemui->textEdit->append(u8"单元格内容:"+aItem->text()); //显示item的文字内容}
}//在表格最后一行添加
void Widget::on_btnAppendLast_clicked()
{QList<QStandardItem*> aItemList;QStandardItem *aItem;for(int i=0; i < COLUMN_COUNT - 1;i++) //不包含最后1列{aItem = new QStandardItem(u8"自定义");aItemList<<aItem;}//获取最后一列的表头文字QString str=m_pItemModel->headerData(m_pItemModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString();aItem=new QStandardItem(str);aItem->setCheckable(true);aItemList<<aItem; //添加到容器m_pItemModel->insertRow(m_pItemModel->rowCount(), aItemList); //插入一行,需要每个Cell的ItemQModelIndex curIndex = m_pItemModel->index(m_pItemModel->rowCount()-1, 0); //创建最后一行的ModelIndex//如果之前点击了表格,清空选择项m_pSelectionModel->clearSelection();//设置刚插入的行为当前选择行m_pSelectionModel->setCurrentIndex(curIndex, QItemSelectionModel::Select);
}void Widget::on_btnAppend_clicked()
{QList<QStandardItem*> aItemList;QStandardItem *aItem;for(int i=0; i<COLUMN_COUNT-1; i++){aItem=new QStandardItem(u8"自定义");aItemList<<aItem;}//获取表头文字QString str = m_pItemModel->headerData(m_pItemModel->columnCount()-1,Qt::Horizontal,Qt::DisplayRole).toString();aItem = new QStandardItem(str);aItem->setCheckable(true);aItemList<<aItem;QModelIndex curIndex = m_pSelectionModel->currentIndex(); //获取当前选中项的模型索引m_pItemModel->insertRow(curIndex.row(),aItemList); //在当前行的前面插入一行m_pSelectionModel->clearSelection(); //清除已有选择m_pSelectionModel->setCurrentIndex(curIndex,QItemSelectionModel::Select);
}//删除选择的行
void Widget::on_btnDeleteSelectedLine_clicked()
{QModelIndex curIndex=m_pSelectionModel->currentIndex();//获取当前选择单元格的模型索引if (curIndex.row() == m_pItemModel->rowCount()-1) //如果是最后一行{m_pItemModel->removeRow(curIndex.row()); //删除最后一行}else{m_pItemModel->removeRow(curIndex.row()); //删除一行,并重新设置当前选择行m_pSelectionModel->setCurrentIndex(curIndex, QItemSelectionModel::Select);}
}//将tableView的数据显示在textEdit
void Widget::on_btnReshowData_clicked()
{ui->textEdit->clear(); //清空QStandardItem *aItem;QString str;//获取表头文字int i,j;for (i=0; i < m_pItemModel->columnCount(); i++){aItem = m_pItemModel->horizontalHeaderItem(i); //获取表头的一个项数据str=str+aItem->text()+"\t"; //用TAB间隔文字}ui->textEdit->append(str); //添加为文本框的一行//获取数据区的每行for (i=0; i < m_pItemModel->rowCount();i++){str="";for(j=0; j<m_pItemModel->columnCount()-1; j++){aItem = m_pItemModel->item(i,j);str = str + aItem->text()+QString::asprintf("\t"); //以 TAB分隔}aItem = m_pItemModel->item(i,j); //最后一行if (aItem->checkState()==Qt::Checked)str = str+"1";elsestr = str+"0";ui->textEdit->append(str);}
}
main.cpp:
#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
运行结果:
三、Qt模型视图代理之:QListView的使用
-
QListView初始化
QStringList strList; strList << u8"北京" << u8"上海" << u8"深圳" << u8"广东"<< u8"南京" << u8"苏州" << u8"西安";//创建数据模型 m_pStringListModel = new QStringListModel(this);//为模型设置StringList,会导入StringList的内容 m_pStringListModel->setStringList(strList);//为listView设置数据模型 ui->listView->setModel(m_pStringListModel);
-
QListView末尾追加行
//在尾部插入一空行, 不添加就把最后一行给替换了 m_pStringListModel->insertRow(m_pStringListModel->rowCount());//获取最后一行 QModelIndex index = m_pStringListModel->index(m_pStringListModel->rowCount()-1, 0); m_pStringListModel->setData(index,"new item", Qt::DisplayRole); //设置显示文字//设置新添加的行选中 ui->listView->setCurrentIndex(index);
-
QListView插入一行
//获取选中 model Index QModelIndex index=ui->listView->currentIndex();//在当前行的前面插入一行 m_pStringListModel->insertRow(index.row()); m_pStringListModel->setData(index,"inserted item",Qt::DisplayRole); ui->listView->setCurrentIndex(index);
-
QListView删除选中的行
//获取当前选中的modelIndex QModelIndex index = ui->listView->currentIndex();//删除当前行 m_pStringListModel->removeRow(index.row());
-
QListView删除所有数据
m_pStringListModel->removeRows(0, m_pStringListModel->rowCount());
-
QListView添加右键菜单
//listview右键菜单 ui->listView->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->listView, &QListView::customContextMenuRequested, this, &Widget::on_showRightMenu);
示例:
widget.h:
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QStringListModel>
#include <QMenu>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:void initMenu();private slots:void on_btnAddItem_clicked();void on_btnDeleteItem_clicked();void on_btnInsert_clicked();void on_btnClearAllData_clicked();void on_btnReshow_clicked();void on_showRightMenu(const QPoint& pos);void OnActionDelete();//链接listview的clicked信号void on_listView_clicked(const QModelIndex &index);private:Ui::Widget *ui;QStringListModel* m_pStringListModel;QMenu *m_pMenu;
};
#endif // WIDGET_H
widget.cpp:
#include "widget.h"
#include "ui_widget.h"
#include <QMenu>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle(u8"QListView使用教程");QStringList strList;strList << u8"北京" << u8"上海" << u8"深圳" << u8"广东"<< u8"南京" << u8"苏州" << u8"西安";//创建数据模型m_pStringListModel = new QStringListModel(this);//为模型设置StringList,会导入StringList的内容m_pStringListModel->setStringList(strList);//为listView设置数据模型ui->listView->setModel(m_pStringListModel);//设置listview编辑属性//双击与选择//ui->listView->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked);initMenu();//listview右键菜单ui->listView->setContextMenuPolicy(Qt::CustomContextMenu);connect(ui->listView, &QListView::customContextMenuRequested, this, &Widget::on_showRightMenu);
}Widget::~Widget()
{delete ui;
}//添加item
void Widget::on_btnAddItem_clicked()
{//在尾部插入一空行, 不添加就把最后一行给替换了m_pStringListModel->insertRow(m_pStringListModel->rowCount());//获取最后一行QModelIndex index = m_pStringListModel->index(m_pStringListModel->rowCount()-1, 0);m_pStringListModel->setData(index,"new item", Qt::DisplayRole); //设置显示文字//设置新添加的行选中ui->listView->setCurrentIndex(index);
}//删除选中的项
void Widget::on_btnDeleteItem_clicked()
{//获取当前选中的modelIndexQModelIndex index = ui->listView->currentIndex();//删除当前行m_pStringListModel->removeRow(index.row());
}//插入一项
void Widget::on_btnInsert_clicked()
{//获取选中 model IndexQModelIndex index=ui->listView->currentIndex();//在当前行的前面插入一行m_pStringListModel->insertRow(index.row());m_pStringListModel->setData(index,"inserted item",Qt::DisplayRole);ui->listView->setCurrentIndex(index);
}//回显listview数据
void Widget::on_btnReshow_clicked()
{//获取数据模型的StringListQStringList tmpList = m_pStringListModel->stringList();ui->textEdit->clear(); //文本框清空for (int i=0; i<tmpList.count();i++){//显示数据模型的StringList()返回的内容ui->textEdit->append(tmpList.at(i));}
}//清除所有数据
void Widget::on_btnClearAllData_clicked()
{m_pStringListModel->removeRows(0, m_pStringListModel->rowCount());
}void Widget::initMenu()
{m_pMenu = new QMenu(ui->listView);QAction *pAc1 = new QAction(u8"删除", ui->listView);QAction *pAc2 = new QAction(u8"插入", ui->listView);QAction *pAc3 = new QAction(u8"置顶", ui->listView);QAction *pAc4 = new QAction(u8"排到最后", ui->listView);m_pMenu->addAction(pAc1);m_pMenu->addAction(pAc2);m_pMenu->addAction(pAc3);m_pMenu->addAction(pAc4);//注意在exec前链接信号槽,因为exec会阻塞主线程,//如果connect写在exec代码之后,信号槽将无法链接connect(pAc1, &QAction::triggered, this, &Widget::OnActionDelete);
}void Widget::on_showRightMenu(const QPoint& pos)
{if(!((ui->listView->selectionModel()->selectedIndexes()).empty())){m_pMenu->exec(QCursor::pos());//在当前鼠标位置显示}
}void Widget::OnActionDelete()
{//获取当前 modelIndexQModelIndex index = ui->listView->currentIndex();//删除当前行m_pStringListModel->removeRow(index.row());
}void Widget::on_listView_clicked(const QModelIndex &index)
{ui->textEdit->clear(); //文本框清空//显示QModelIndex的行、列号ui->textEdit->append(QString::asprintf(u8"当前项:row=%d, column=%d",index.row(),index.column()));
}
main.cpp:
#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
运行结果: