Python 选择在带有ComboBox的QTableWidget中不起作用-复制事件未触发

Python 选择在带有ComboBox的QTableWidget中不起作用-复制事件未触发,python,pyqt,pyqt5,qtablewidget,qcombobox,Python,Pyqt,Pyqt5,Qtablewidget,Qcombobox,QTableWidget(PyQt5)中的嵌入式组合框似乎阻止了选择和复制等事件的触发。选择和复制事件在没有组合框的情况下可以正常工作 我正在使用eventFilters捕获复制事件(CTRL+C)。如果没有组合框,一切都会正常工作。您可以选择任意范围的单元格,并将其复制/粘贴到Excel中 一旦我添加了组合框,包含组合框的选择似乎不再触发事件。事实上,当选择包含组合框时,它会从蓝色变为灰色 有趣的是,当您选择整个表或整行时,它将保持蓝色,我可以复制和粘贴所有内容,包括组合框。不包含组合框的选择

QTableWidget(PyQt5)中的嵌入式组合框似乎阻止了选择和复制等事件的触发。选择和复制事件在没有组合框的情况下可以正常工作

我正在使用eventFilters捕获复制事件(CTRL+C)。如果没有组合框,一切都会正常工作。您可以选择任意范围的单元格,并将其复制/粘贴到Excel中

一旦我添加了组合框,包含组合框的选择似乎不再触发事件。事实上,当选择包含组合框时,它会从蓝色变为灰色

有趣的是,当您选择整个表或整行时,它将保持蓝色,我可以复制和粘贴所有内容,包括组合框。不包含组合框的选择也可以正常工作

下面是带有复制事件过滤器的QTableWidget的最低工作示例

import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(528, 436)
        self.tableWidget = QtWidgets.QTableWidget(Dialog)
        self.tableWidget.setGeometry(QtCore.QRect(0, 0, 523, 399))

        self.tableWidget.setColumnCount(4)
        self.tableWidget.setRowCount(3)

class dialogForm(QDialog):
    def __init__(self, ui_layout):
        QDialog.__init__(self)
        self.ui = ui_layout
        ui_layout.setupUi(self)

        self.cbItems = ["A", "B", "C", "D"]
        self.setupComboBoxAll()

        self.ui.tableWidget.installEventFilter(self)

    def setupComboBox(self, row):
        comboBoxAircraftName = QComboBox()
        comboBoxAircraftName.setProperty("row", row)
        comboBoxAircraftName.setProperty("col", 1)        
        for t in self.cbItems:
            comboBoxAircraftName.addItem(t)
        self.ui.tableWidget.setCellWidget(row,1,comboBoxAircraftName)        

    def setupComboBoxAll(self):
        for i in range(0, self.ui.tableWidget.rowCount()):
            self.setupComboBox(i)

###########################
### NOT BEING TRIGGERED
###########################
   # Used for copying and pasting
    def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.KeyPress and
            event.matches(QtGui.QKeySequence.Copy)):
            self.copySelection()
            return True

        return super(dialogForm, self).eventFilter(source, event)

    # Allow copying from QTableWidget and Pasting into Excel
    def copySelection(self):
        selection = self.ui.tableWidget.selectedIndexes()

        if selection:
            rows = sorted(index.row() for index in selection)
            columns = sorted(index.column() for index in selection)
            rowcount = rows[-1] - rows[0] + 1
            colcount = columns[-1] - columns[0] + 1
            table = [[''] * colcount for _ in range(rowcount)]
            for index in selection:
                row = index.row() - rows[0]
                column = index.column() - columns[0]
                if column == 1:
                    table[row][column] = self.ui.tableWidget.cellWidget(row, column).currentText()
                else:
                    table[row][column] = index.data()
            stream = io.StringIO()
            csv.writer(stream, delimiter='\t').writerows(table)
            QtWidgets.qApp.clipboard().setText(stream.getvalue())


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = dialogForm(Ui_Dialog())
    window.show()
    sys.exit(app.exec_())

main()

我正在Windows 10上工作。Anaconda Python 3.6.3

解决方案很简单,也可以在
QComboBox
中安装过滤器,如下所示:

def setupComboBox(self, row):
    comboBoxAircraftName = QComboBox()
    comboBoxAircraftName.setProperty("row", row)
    comboBoxAircraftName.setProperty("col", 1)

    comboBoxAircraftName.installEventFilter(self)

    comboBoxAircraftName.addItems(self.cbItems)
    self.ui.tableWidget.setCellWidget(row, 1 ,comboBoxAircraftName)  
另一个更简单的解决方案是使用
QShortcut

class dialogForm(QDialog):
    def __init__(self, ui_layout):
        QDialog.__init__(self)
        self.ui = ui_layout
        ui_layout.setupUi(self)

        self.cbItems = ["A", "B", "C", "D"]
        self.setupComboBoxAll()

        shorcut = QtWidgets.QShortcut(QtGui.QKeySequence.Copy, self.ui.tableWidget)
        shorcut.activated.connect(self.copySelection)

    def setupComboBox(self, row):
        comboBoxAircraftName = QComboBox()
        comboBoxAircraftName.setProperty("row", row)
        comboBoxAircraftName.setProperty("col", 1)
        comboBoxAircraftName.addItems(self.cbItems)
        self.ui.tableWidget.setCellWidget(row, 1 ,comboBoxAircraftName)  

    def setupComboBoxAll(self):
        for i in range(self.ui.tableWidget.rowCount()):
            self.setupComboBox(i)

    # Allow copying from QTableWidget and Pasting into Excel
    def copySelection(self):
        selection = self.ui.tableWidget.selectedIndexes()

        if selection:
            rows = sorted(index.row() for index in selection)
            columns = sorted(index.column() for index in selection)
            rowcount = rows[-1] - rows[0] + 1
            colcount = columns[-1] - columns[0] + 1
            table = [[''] * colcount for _ in range(rowcount)]
            for index in selection:
                row = index.row() - rows[0]
                column = index.column() - columns[0]
                if column == 1:
                    table[row][column] = self.ui.tableWidget.cellWidget(row, column).currentText()
                else:
                    table[row][column] = index.data()
            stream = io.StringIO()
            csv.writer(stream, delimiter='\t').writerows(table)
            QtWidgets.qApp.clipboard().setText(stream.getvalue())