“Table”对象没有属性“tableWidget”PyQt5

2024-10-04 03:20:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试更改QTableWidget mouse pressed事件方法,以根据用户是右键单击还是左键单击对单元格项执行不同的操作。左键单击self.tableWidget中的单元格时,出现以下错误:

AttributeError: 'Table' object has no attribute 'tableWidget' (line 114 [commented below])

下面是我的代码:

from PyQt5 import QtCore, QtGui, QtWidgets
from WordSearch import WordSearch as ws

ws = ws()


class Table(QtWidgets.QTableWidget): #overwriting QTableWidgets to allow for right click events
    def __init__(self, *args, **kwargs):
        QtWidgets.QTableWidget.__init__(self, *args, **kwargs)

    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            item = self.itemAt(event.pos())
            print (item.row(), item.column()) #FOR DEBUGGUNG
            Ui_MainWindow.leftClickLetter(self, item.row(), item.column())

        elif event.button() == QtCore.Qt.RightButton:
            print("RIGHT CLICK!") #FOR DEBUGGING
        QtWidgets.QTableWidget.mousePressEvent(self, event)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
         .....

         self.generate.clicked.connect(self.generateTable)

         .....

    def generateTable(self):

        self.tableWidget = Table(self.centralwidget)
        self.tableWidget.setObjectName("tableWidget")

        self.tableWidget.setColumnCount(int(self.size.text()))
        self.tableWidget.setRowCount(int(self.size.text()))

        self.tableWidget.show()

    def leftClickLetter(self, row, col): 
        item = self.tableWidget.item(row, col) #Line 114
        item.setBackground(QtGui.QColor(216,191,216))
        if (row, col) not in self.coordsToCheck:
            self.coordsToCheck.append((row,col))

        self.tableWidget.clearSelection()

我删掉了一些我认为不相关的代码,但如果我需要添加,请告诉我。generateTable()总是在leftClickLetter()之前调用,因此self.tableWidget应该是Table类型的正确变量名


Tags: selfeventwsdeftablecolitemrow
1条回答
网友
1楼 · 发布于 2024-10-04 03:20:45

说明:

要了解问题,应分析以下示例:

class A:
    def foo(self, arg1, arg2):
        print(self)


class B:
    pass


b = B()
A.foo(b, "2", 3)

输出:

<__main__.B object at 0x7fb364501070>

如您所见,对象“self”不是指“A”实例,而是指传递给该方法的第一个参数,为什么会出现这种问题?因为您试图通过类使用方法,但必须使用实例,例如:

b = B()
a = A()
a.foo(b, "2")

输出:

<__main__.A object at 0x7fd3139a4f40>

我们看到“自我”指的是“A”类的客体

以上是由于对OOP知之甚少而导致的错误,因此我的建议是查看您在该主题上的注释。

解决方案:

注意:首先,不建议修改Qt Designer生成的类,因此您必须还原该类,以便应用我的解决方案

在您的情况下,无需覆盖任何方法,因为如果单击了某个项目,会有多个信号通知您:

  • ^{}

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            # ..
    
    
    class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setupUi(self)
            self.generate.clicked.connect(self.generate_table)
            self.coordsToCheck = []
            self.tables = []
    
        def generate_table(self):
    
            try:
                size = int(self.size.text())
            except ValueError as e:
                print("error", e)
            else:
                tableWidget = QtWidgets.QTableWidget()
                tableWidget.setColumnCount(size)
                tableWidget.setRowCount(size)
                tableWidget.show()
                tableWidget.itemClicked.connect(self.on_item_clicked)
                self.tables.append(tableWidget)
    
        @QtCore.pyqtSlot("QTableWidgetItem*")
        def on_item_clicked(self, it):
            row, col = it.row(), it.column()
            it.setBackground(QtGui.QColor(216, 191, 216))
            if (row, col) not in self.coordsToCheck:
                self.coordsToCheck.append((row, col))
            it.tableWidget().clearSelection()
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())
    
  • ^{}

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            # ...
    
    
    class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setupUi(self)
            self.generate.clicked.connect(self.generate_table)
            self.coordsToCheck = []
            self.tables = []
    
        def generate_table(self):
    
            try:
                size = int(self.size.text())
            except ValueError as e:
                print("error", e)
            else:
                tableWidget = QtWidgets.QTableWidget()
                tableWidget.setColumnCount(size)
                tableWidget.setRowCount(size)
                tableWidget.show()
                tableWidget.clicked.connect(self.on_clicked)
                self.tables.append(tableWidget)
    
        @QtCore.pyqtSlot(QtCore.QModelIndex)
        def on_clicked(self, index):
            tableWidget = self.sender()
            row, col = index.row(), index.column()
            tableWidget.model().setData(
                index, QtGui.QColor(216, 191, 216), QtCore.Qt.BackgroundRole
            )
            if (row, col) not in self.coordsToCheck:
                self.coordsToCheck.append((row, col))
            tableWidget.clearSelection()
    
    
    if __name__ == "__main__":
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())
    

更新:

如果要检测右键单击,则必须创建信号,而不是直接调用方法:

class TableWidget(QtWidgets.QTableWidget):
    rightClicked = QtCore.pyqtSignal(QtCore.QModelIndex)

    def mouseReleaseEvent(self, event):
        super().mouseReleaseEvent(event)
        if event.button() == QtCore.Qt.RightButton:
            self.rightClicked.emit(self.indexAt(event.pos()))
def generate_table(self):
    try:
        size = int(self.size.text())
    except ValueError as e:
        print("error", e)
    else:
        tableWidget = TableWidget(size, size)
        tableWidget.show()
        tableWidget.clicked.connect(self.on_left_clicked)
        tableWidget.rightClicked.connect(self.on_right_clicked)
        self.tables.append(tableWidget)

@QtCore.pyqtSlot(QtCore.QModelIndex)
def on_left_clicked(self, index):
    self.change_color(self.sender(), index, QtGui.QColor(216, 191, 216))

@QtCore.pyqtSlot(QtCore.QModelIndex)
def on_right_clicked(self, index):
    self.change_color(self.sender(), index, None)

def change_color(self, view, index, color):
    if not isinstance(view, QtWidgets.QAbstractItemView):
        return
    model = view.model()
    if model is None:
        return
    model.setData(index, color, QtCore.Qt.BackgroundRole)
    view.clearSelection()

相关问题 更多 >