【问题标题】:'Table' object has no attribute 'tableWidget' PyQt5“表”对象没有属性“tableWidget”PyQt5
【发布时间】:2020-05-16 21:18:08
【问题描述】:

我正在尝试更改 QTableWidget 鼠标按下事件方法,以根据用户是右键单击还是左键单击来对单元格项执行不同的操作。当我左键单击 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 类型变量名。

【问题讨论】:

    标签: python pyqt pyqt5 qtablewidget


    【解决方案1】:

    说明:

    要理解问题,应该分析下面的例子:

    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>
    

    我们看到“self”指的是“A”类的对象。

    以上是由于对OOP知之甚少而导致的错误,所以我的建议是查看您关于该主题的笔记。

    解决办法:

    注意:首先不建议修改Qt Designer生成的类,所以必须恢复类,这样我的方案才能应用。

    在您的情况下,没有必要覆盖任何方法,因为有几个信号会通知您是否单击了某个项目:

    • itemClicked

      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_())
      
    • clicked

      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()
    

    【讨论】:

    • 谢谢!我的问题是我希望能够右键单击单元格并将背景颜色更改回正常,但我找不到任何专门用于右键单击单元格的信号。
    猜你喜欢
    • 2022-01-24
    • 2017-06-10
    • 2019-06-16
    • 1970-01-01
    • 2017-10-06
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多