首页 > 解决方案 > 在初始化类pyqt5之外处理事件

问题描述

使用Here and There中的代码,我制作了一个 GUI,以较小的规模展示我的项目。

我有一个 qTableView,包含大量行,并且在每一行上我都有一个删除和一个编辑按钮。单击时,它应该编辑或删除当前行。仅使用第一个 source时,它​​完全按预期工作,但是一旦我处理按钮类之外的单击,它就会停止工作。

每次我尝试编辑或删除时,self.sender() 或 QtWidgets.qApp.focusWidget() 视为发送者的按钮具有坐标 [0,0],即使它绝对不是坐标。

我在各种网站上搜索过,但找不到这个确切的问题。我做错了什么,我能做些什么来解决这个问题?

我的代码:

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QFileDialog, QMessageBox

class EditButtonsWidget(QtWidgets.QWidget):
    # Credit to : https://stackoverflow.com/a/29764914/13812144

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

        # add your buttons
        layout = QtWidgets.QHBoxLayout()

        # adjust spacings to your needs
        layout.setContentsMargins(0,0,0,0)
        layout.setSpacing(0)
        
        self.editButton = QtWidgets.QPushButton('edit')
        self.deleteButton = QtWidgets.QPushButton('del')
        
        self.buttonRow = 0
        # add your buttons
        layout.addWidget(self.editButton)
        layout.addWidget(self.deleteButton)

        self.setLayout(layout)

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self,parent)
        self.table = QtWidgets.QTableWidget()
        self.table.setColumnCount(3)
        self.setCentralWidget(self.table)
        data1 = ['row1','row2','row3','row4']
        data2 = ['1','2.0','3.00000001','3.9999999']

        self.table.setRowCount(4)

        for index in range(4):
            item1 = QtWidgets.QTableWidgetItem(data1[index])
            self.table.setItem(index,0,item1)
            item2 = QtWidgets.QTableWidgetItem(data2[index])
            self.table.setItem(index,1,item2)
            self.btn_sell = EditButtonsWidget()
            self.btn_sell.editButton.clicked.connect(self.handleButtonClicked)
            self.table.setCellWidget(index,2,self.btn_sell)

    def handleButtonClicked(self):
        #button = QtWidgets.qApp.focusWidget()
        button = self.sender()
        index = self.table.indexAt(button.pos())
        if index.isValid():
            print(index.row(), index.column())
            
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = MainWindow()
    MainWindow.show()
    sys.exit(app.exec_())

标签: pyqt5

解决方案


该位置必须是在 QTableWidget 中设置的小部件,而不是它的一个子部件。

在这种情况下,最好将 EditButtonsWidget 视为一个黑盒子,并将按钮的单击信号公开为新信号,以便发送者是 EditButtonsWidget 而不再是按钮:

class EditButtonsWidget(QtWidgets.QWidget):
    edit_clicked = QtCore.pyqtSignal()
    delete_clicked = QtCore.pyqtSignal()

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

        # add your buttons
        layout = QtWidgets.QHBoxLayout(self)

        # adjust spacings to your needs
        layout.setContentsMargins(0,0,0,0)
        layout.setSpacing(0)
        
        self.editButton = QtWidgets.QPushButton('edit')
        self.deleteButton = QtWidgets.QPushButton('del')
        
        # add your buttons
        layout.addWidget(self.editButton)
        layout.addWidget(self.deleteButton)

        self.editButton.clicked.connect(self.edit_clicked)
        self.deleteButton.clicked.connect(self.delete_clicked)
for index in range(4):
    item1 = QtWidgets.QTableWidgetItem(data1[index])
    self.table.setItem(index,0,item1)
    item2 = QtWidgets.QTableWidgetItem(data2[index])
    self.table.setItem(index,1,item2)
    self.btn_sell = EditButtonsWidget()
    self.btn_sell.edit_clicked.connect(self.handleButtonClicked) # <---
    self.table.setCellWidget(index,2,self.btn_sell)

推荐阅读