简体   繁体   English

如何在pyqt中将鼠标悬停在QTableWidget项目的事件上?

[英]How to catch mouse over event of QTableWidget item in pyqt?

当我将鼠标悬停在QTableWidget的项目上时,我想做的就是更改QTableWidget项的颜色。

Firstly, the table widget needs to have mouse-tracking switched on to get the hover events. 首先,表格小部件需要打开鼠标跟踪才能获取悬停事件。

Secondly, we need to find some signals that tell us when the mouse enters and leaves the table cells, so that the background colours can be changed at the right times. 其次,我们需要找到一些信号来告诉我们鼠标何时进入和离开表格单元格,以便可以在正确的时间更改背景颜色。

The QTableWidget class has the cellEntered / itemEntered signals, but there is nothing for when the mouse leaves a cell. QTableWidget类具有cellEntered / itemEntered信号,但是当鼠标离开单元格时没有任何作用。 So, we will need to create some custom signals to do that. 因此,我们将需要创建一些自定义信号来做到这一点。

The TableWidget class in the demo script below sets up the necessary cellExited / itemExited signals, and then shows how everything can be hooked up to change the item background when hovering with the mouse: 下面的演示脚本中的TableWidget类设置必要的cellExited / itemExited信号,然后说明如何使用鼠标悬停以挂钩一切以更改项目背景:

from PyQt4 import QtGui, QtCore

class TableWidget(QtGui.QTableWidget):
    cellExited = QtCore.pyqtSignal(int, int)
    itemExited = QtCore.pyqtSignal(QtGui.QTableWidgetItem)

    def __init__(self, rows, columns, parent=None):
        QtGui.QTableWidget.__init__(self, rows, columns, parent)
        self._last_index = QtCore.QPersistentModelIndex()
        self.viewport().installEventFilter(self)

    def eventFilter(self, widget, event):
        if widget is self.viewport():
            index = self._last_index
            if event.type() == QtCore.QEvent.MouseMove:
                index = self.indexAt(event.pos())
            elif event.type() == QtCore.QEvent.Leave:
                index = QtCore.QModelIndex()
            if index != self._last_index:
                row = self._last_index.row()
                column = self._last_index.column()
                item = self.item(row, column)
                if item is not None:
                    self.itemExited.emit(item)
                self.cellExited.emit(row, column)
                self._last_index = QtCore.QPersistentModelIndex(index)
        return QtGui.QTableWidget.eventFilter(self, widget, event)

class Window(QtGui.QWidget):
    def __init__(self, rows, columns):
        QtGui.QWidget.__init__(self)
        self.table = TableWidget(rows, columns, self)
        for column in range(columns):
            for row in range(rows):
                item = QtGui.QTableWidgetItem('Text%d' % row)
                self.table.setItem(row, column, item)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.table)
        self.table.setMouseTracking(True)
        self.table.itemEntered.connect(self.handleItemEntered)
        self.table.itemExited.connect(self.handleItemExited)

    def handleItemEntered(self, item):
        item.setBackground(QtGui.QColor('moccasin'))

    def handleItemExited(self, item):
        item.setBackground(QtGui.QTableWidgetItem().background())

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window(6, 3)
    window.setGeometry(500, 300, 350, 250)
    window.show()
    sys.exit(app.exec_())

You can achieve your goal pretty easily using the proper signals as proved by the following simple code: 如下面的简单代码所示,您可以使用适当的信号轻松实现目标:

from PyQt4.QtGui import *
from PyQt4.QtCore import *

class TableViewer(QMainWindow):
    def __init__(self, parent=None):
        super(TableViewer, self).__init__(parent)
        self.table = QTableWidget(3, 3)
        for row in range (0,3):
            for column in range(0,3):
                item = QTableWidgetItem("This is cell {} {}".format(row+1, column+1))
                self.table.setItem(row, column, item)
        self.setCentralWidget(self.table)

        self.table.setMouseTracking(True)

        self.current_hover = [0, 0]
        self.table.cellEntered.connect(self.cellHover)

    def cellHover(self, row, column):
        item = self.table.item(row, column)
        old_item = self.table.item(self.current_hover[0], self.current_hover[1])
        if self.current_hover != [row,column]:
            old_item.setBackground(QBrush(QColor('white')))
            item.setBackground(QBrush(QColor('yellow')))
        self.current_hover = [row, column]


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    tv = TableViewer()
    tv.show()
    sys.exit(app.exec_())

You may be interested in other signals too, especially itemEntered . 您可能也对其他信号感兴趣,尤其是itemEntered However, if you want total control over the editing and display of items then using delegates (via the QTableWidget.setItemDelegate method) is strongly recommended. 但是,如果要完全控制项目的编辑和显示,则强烈建议使用委托(通过QTableWidget.setItemDelegate方法)。

UPDATE : 更新

sorry, I had forgotten the second part of the problem ie what happens when the mouse exits a cell. 抱歉,我忘记了问题的第二部分,即当鼠标退出细胞时会发生什么。 Even then the problem can be solved easily without using events. 即使这样,也可以不使用事件就轻松解决问题。 See the updated code, please. 请查看更新的代码。

There are no events based on QTableWidgetItem, but you can do this: 没有基于QTableWidgetItem的事件,但是您可以执行以下操作:

  • reimplement the mouseMoveEvent() of QTableWidget, you can get the mouse position; 重新实现QTableWidget的mouseMoveEvent() ,可以获得鼠标的位置;
  • use itemAt() method to get the item under your mouse cursor; 使用itemAt()方法获取鼠标光标下的项目;
  • customize your item; 自定义您的物品;

This may simalute what you want. 这可能会最小化您想要的内容。

I know this is old but wanted to update a couple of parts to it as I came across this page looking for a similar solution. 我知道这已经很老了,但是当我遇到此页面寻找类似的解决方案时,想对其进行更新。 This has a couple of parts to it, one is similar to the above but avoids the NoneType error if the cell is empty. 它有两个部分,一个与上面相似,但是如果单元格为空,则避免了NoneType错误。 Additionally, it will change the color of the highlighted cell, but also update a tooltip for the cell to display the contents of the cell in a tooltip. 此外,它将更改突出显示的单元格的颜色,但还会更新该单元格的工具提示,以在工具提示中显示该单元格的内容。 Nice if you have cells with runoffs 123... 如果您的单元格的径流量为12​​3,则效果很好。

Sure it could be cleaned up a bit, but works for PyQt5. 当然可以清理一点,但是可以用于PyQt5。 Cheers! 干杯!

def cellHover(self, row, column):
    item = self.My_Table1.item(row, column)
    old_item = self.My_Table1.item(self.current_hover[0], self.current_hover[1])
    if item is not None:
        if self.current_hover != [row,column]:
            text = item.text()
            if text is not None:
                self.My_Table1.setToolTip(text)
                item.setBackground(QBrush(QColor('#bbd9f7')))
                old_item.setBackground(QBrush(QColor('white')))
            self.current_hover = [row, column]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM