资讯动态

QTableView中单元下拉框代理实现(附源码)

发布时间:2026/10/15 2:11:46 来源:尧图企业网站定制
上代码功能介绍1、支持单击弹出下拉框2、支持双击直接编辑单元格数据3、支持数据不在下拉框中时自动将该数据添加到下拉框一、头文件class ComboBoxDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit ComboBoxDelegate(); /// /// \brief ComboBoxDelegate /// \param items 下拉框选项 /// \param parent /// explicit ComboBoxDelegate(QStringList items, QObject *parent nullptr); /// 重写 QStyledItemDelegate 的虚函数 QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem option,const QModelIndex index) const override; ///重写编辑函数 void setEditorData(QWidget *editor, const QModelIndex index) const override; ///重写设置模型数据函数 void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex index) const override; void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem option,const QModelIndex index) const override; ///重写编辑器事件函数 bool editorEvent(QEvent *event,QAbstractItemModel *model,const QStyleOptionViewItem option,const QModelIndex index) override; ///重写绘制函数 void paint(QPainter *painter,const QStyleOptionViewItem option,const QModelIndex index) const override; ///绘制控件右侧三角形 void drawTriangle(QPainter *painter, const QRect rect) const; private slots: ///当输入的数据不在下拉框列表时需要添加到下拉框 void onItemsChanged(QString value); ///鼠标单击事件响应函数 void onSingleClick(); ///控制单击时显示下拉框 void onStateChanged(bool val) { m_state val; } signals: ///当输入字符不在下拉框列表时会发送该信号 void itemsChange(QString value) const; ///当单击事件产生时会发送该信号 void stateChanged(bool val) const; private: QStringList m_items; QModelIndex m_clickedIndex; QStyleOptionViewItem m_clickedOption; QTimer *m_clickTimer; bool m_state false; };二、构造函数ComboBoxDelegateComboBoxDelegate::ComboBoxDelegate(QStringList items, QObject *parent) : QStyledItemDelegate(parent) , m_items(items) { m_clickTimer new QTimer(this); m_clickTimer-setInterval(200); m_clickTimer-setSingleShot(true); // m_clickTimer-setInterval(QApplication::doubleClickInterval()); connect(m_clickTimer, QTimer::timeout, this, ComboBoxDelegate::onSingleClick); connect(this,ComboBoxDelegate::itemsChange,this,ComboBoxDelegate::onItemsChanged); connect(this,ComboBoxDelegate::stateChanged,this,ComboBoxDelegate::onStateChanged); }代理在实例化时必须传入下拉框控件列表用于显示下拉菜单构造函数中m_clickTimer 为一个定时器主要用于editorEvent函数处理单击时间在editorEvent函数中按键被按下后会启用该定时器200ms超时会被认为是单击并调用函数onSingleClick处理单击动作三、重写createEditor函数单元格编辑器QWidget *ComboBoxDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem option,const QModelIndex index) const { Q_UNUSED(option); Q_UNUSED(index); // 创建QComboBox作为编辑器 QComboBox *comboBox new QComboBox(parent); comboBox-setEditable(true); // 允许编辑 comboBox-setInsertPolicy(QComboBox::InsertAtBottom); // 设置插入策略 comboBox-addItems(m_items); return comboBox; }该函数在单元格被双击会被调用因此在单元格双击后创建一个QComboBox实例并将下拉菜单选项设置到控件中四、重写setEditorData函数单元格编辑状态void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex index) const { QComboBox *comboBox qobject_castQComboBox*(editor); if (!comboBox) return; // 获取当前单元格的显示文本 QString currentText index.data(Qt::DisplayRole).toString(); // 设置当前显示文本 comboBox-setCurrentText(currentText); if(m_state) { comboBox-showPopup(); emit stateChanged(false); } }单元格在被双击后会首先调用createEditor函数用于创建编辑器并会编辑器对象然后再调用setEditorData函数用于用户对数据进行编辑setEditorData参数中的QWidget *editor则是createEditor返回的对象该函数被调用后会首先将单元格显示的值设置为下拉框控件的当前选项当m_state为True时则标识该函数被调用的链路是通过单击事件产生的则需要自动弹出下拉框以此实现单击时弹出下拉框弹出后则设置m_state状态为false标识单击事件已经被正确处理五、重写setModelData函数当下拉框中的数据发生变化时被调用void ComboBoxDelegate::setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex index) const { QComboBox *comboBox qobject_castQComboBox*(editor); if (!comboBox) return; QString currentText comboBox-currentText(); // 如果编辑后的文本不在当前下拉框选项中则添加到下拉框 if (!m_items.contains(currentText)) { emit itemsChange(currentText); } // 更新模型数据 if(index.data().toString() ! currentText) { model-setData(index, currentText, Qt::EditRole); } }该函数在编辑事件推出后会被自动调用用于设置当前单元格的值如果值没有发生变化时则不对单元的值进行修改六、重写updateEditorGeometry函数更新编辑器void ComboBoxDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem option,const QModelIndex index) const { Q_UNUSED(index); editor-setGeometry(option.rect); }七、重写editorEvent函数编辑事件处理bool ComboBoxDelegate::editorEvent(QEvent *event,QAbstractItemModel *model,const QStyleOptionViewItem option,const QModelIndex index) { if (event-type() QEvent::MouseButtonPress) { QMouseEvent *mouseEvent static_castQMouseEvent*(event); if (mouseEvent-button() Qt::LeftButton) { // 停止之前的计时器 m_clickTimer-stop(); // 保存点击的信息 m_clickedIndex index; m_clickedOption option; // 启动计时器来判断是单击还是双击 m_clickTimer-start(); return true; // 事件已处理 } } else if (event-type() QEvent::MouseButtonDblClick) { QMouseEvent *mouseEvent static_castQMouseEvent*(event); if (mouseEvent-button() Qt::LeftButton) { // 停止计时器避免单击事件触发 m_clickTimer-stop(); // 双击 - 进入编辑模式 QTableView *tableView qobject_castQTableView*(this-parent()); if (tableView) { tableView-edit(index); } return true; // 事件已处理 } } return QStyledItemDelegate::editorEvent(event, model, option, index); }当鼠标左键按下时启用定时器m_clickTimer如果定时器m_clickTimer超时则会被处理成单击事件如果时双击事件则调用tableView的edit函数使得单元格进行编辑状态edit函数被调用后会自动调用createEditor方法八、重写paint函数绘制^符号标识该单元格是个下拉框void ComboBoxDelegate::paint(QPainter *painter,const QStyleOptionViewItem option,const QModelIndex index) const { QStyleOptionViewItem opt option; // 计算文本显示区域 int textWidth opt.rect.width() - 17; // 调整文本显示区域 opt.rect.setWidth(textWidth); // 首先调用基类的paint方法绘制文本内容 QStyledItemDelegate::paint(painter, opt, index); // 在单元格右侧绘制三角形 drawTriangle(painter, option.rect); } void ComboBoxDelegate::drawTriangle(QPainter *painter, const QRect rect) const { painter-save(); // 设置三角形颜色 painter-setPen(QPen(Qt::black, 1.4)); //painter-setBrush(QBrush(Qt::gray)); // 计算三角形的位置在单元格右侧 H 8 ,W 10 int triangleSize 8; // 三角形大小 int margin 4; // 右边距 QPointF topPoint, leftPoint, rightPoint; // 计算三角形的三个顶点向下指的三角形 topPoint QPointF(rect.right() - margin - triangleSize/2,rect.center().y()-2); leftPoint QPointF(rect.right() - margin - triangleSize, rect.center().y()2); rightPoint QPointF(rect.right() - margin,rect.center().y()2); // 绘制三角形 QLine line_1(leftPoint.toPoint(),topPoint.toPoint()); QLine line_2(rightPoint.toPoint(),topPoint.toPoint()); QVectorQLine lines; lines line_1 line_2; painter-drawLines(lines); //绘制矩形区域 painter-setPen(QPen(Qt::black, 1)); QRect userRect; // userRect.setHeight(rect.height()); // userRect.setWidth(16); userRect.setLeft(rect.right()-17); userRect.setRight(rect.right()-1); userRect.setTop(rect.top()); userRect.setBottom(rect.bottom()-1); //painter-drawRect(userRect); // 恢复painter状态 painter-restore(); }九、信号槽的调用void ComboBoxDelegate::onItemsChanged(QString value) { m_items.append(value); } void ComboBoxDelegate::onSingleClick() { emit stateChanged(true); QTableView *tableView qobject_castQTableView*(this-parent()); if (tableView) { tableView-edit(m_clickedIndex); } }

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑