You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt中如何让QTableView的编辑器跨两列显示?

问题

我正在开发一个基于PyQt的项目,遇到了QTableView及其项编辑器的问题。我的TableModel包含两列耦合紧密、需同步修改的数据。我已重写QStyledItemDelegate类,实现了基于QComboBox的编辑器,这部分功能正常。但我需要让编辑器跨两列显示,目前找到的示例仅能在用户点击的单个单元格打开编辑器,且通过重写updateEditorGeometry方法基于option参数调整几何。请问能否在updateEditorGeometry方法中获取邻列宽度,计算两列总宽度来调整QComboBox编辑器的几何?

当前简化版QStyledItemDelegate子类代码如下:

class ComboBoxDelegate(QStyledItemDelegate):

  def __init__(self, parent=None):
    super(SpinBoxDelegate, self).__init__(parent)

  def createEditor(self, parent, option, index):
    editor = QComboBox(parent)
    return editor

  def setEditorData(self, editor, index):
    pass


  def setModelData(self, editor, model, index):
    pass


  def updateEditorGeometry(self, editor, option, index):
    row = index.row()
    column = index.column()
    if column == 1:
        neighbourIndex = index.model().index(row, 0, QModelIndex())
    editor.setGeometry(option.rect)
解决方案

完全可以通过updateEditorGeometry实现跨列编辑器,核心是从QTableView中获取目标列的宽度(Model不存储视图的列宽信息),再调整编辑器的几何区域。

具体实现步骤:

  1. 修正代码错误:__init__方法里的super(SpinBoxDelegate, self)需改为super(ComboBoxDelegate, self),否则会引发继承类不匹配的错误。
  2. 在updateEditorGeometry中,通过option.widget获取当前QTableView实例,调用columnWidth()方法获取指定列的宽度。
  3. 根据当前点击的列,计算编辑器的起始坐标和总宽度:
    • 若点击第0列:编辑器从第0列起始位置开始,宽度为两列宽度之和
    • 若点击第1列:编辑器向左偏移第0列的宽度,宽度同样为两列之和
  4. 用调整后的区域重新设置编辑器几何。

修改后的完整代码:

from PyQt5.QtWidgets import QStyledItemDelegate, QComboBox, QTableView, QRect
from PyQt5.QtCore import Qt

class ComboBoxDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super(ComboBoxDelegate, self).__init__(parent)

    def createEditor(self, parent, option, index):
        editor = QComboBox(parent)
        # 可在此添加下拉选项
        # editor.addItems(["选项A", "选项B", "选项C"])
        return editor

    def setEditorData(self, editor, index):
        # 从模型加载数据到编辑器
        current_value = index.model().data(index, Qt.DisplayRole)
        if current_value in [editor.itemText(i) for i in range(editor.count())]:
            editor.setCurrentText(current_value)

    def setModelData(self, editor, model, index):
        # 将编辑器数据同步到模型,同时更新关联列
        selected_value = editor.currentText()
        model.setData(index, selected_value, Qt.EditRole)
        # 同步修改邻列数据
        neighbor_col = 1 if index.column() == 0 else 0
        neighbor_index = model.index(index.row(), neighbor_col)
        model.setData(neighbor_index, f"{selected_value}_同步值", Qt.EditRole)

    def updateEditorGeometry(self, editor, option, index):
        table_view = option.widget
        if not isinstance(table_view, QTableView):
            editor.setGeometry(option.rect)
            return
        
        col = index.column()
        # 获取两列宽度
        col0_width = table_view.columnWidth(0)
        col1_width = table_view.columnWidth(1)
        total_width = col0_width + col1_width

        # 计算编辑器的位置与大小
        rect = option.rect
        if col == 0:
            new_rect = QRect(rect.x(), rect.y(), total_width, rect.height())
        elif col == 1:
            new_rect = QRect(rect.x() - col0_width, rect.y(), total_width, rect.height())
        else:
            new_rect = rect
        
        editor.setGeometry(new_rect)

额外说明:

  • 编辑器作为QTableView的子控件,调整x坐标不会超出视图范围,只要计算逻辑正确就能实现跨列显示效果。
  • setModelData方法中可直接同步修改两列数据,满足耦合数据同步更新的需求。
  • 若后续需要支持更多列的跨列显示,可扩展列宽计算逻辑。

内容的提问来源于stack exchange,提问作者BVZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 11:03:22