Python 单击空白区域时禁用选择/背景色

Python 单击空白区域时禁用选择/背景色,python,pyqt5,Python,Pyqt5,我目前正在使用QTableWidget编写一个GUI来分析CSV文件。在默认情况下,我可以单击一个单元格并选择它,但没有办法取消选择(我猜)。此外,我还有一个功能,可以通过搜索突出显示我想要的单元格。现在,我想要一个功能,我可以单选空白区域,取消选择/禁用突出显示的单元格。空白是指主QtableWidget之外的区域 我知道我需要用一个鼠标压力器,逻辑是 if # mouse click on the blank area and # there's at least one cell sele

我目前正在使用QTableWidget编写一个GUI来分析CSV文件。在默认情况下,我可以单击一个单元格并选择它,但没有办法取消选择(我猜)。此外,我还有一个功能,可以通过搜索突出显示我想要的单元格。现在,我想要一个功能,我可以单选空白区域,取消选择/禁用突出显示的单元格。空白是指主QtableWidget之外的区域

我知道我需要用一个鼠标压力器,逻辑是

if # mouse click on the blank area and # there's at least one cell selected:
   # deselect the cell

elif  #mouse click on the blank area and # there's at least one cell highlightended:
    # disable the background colour
我不知道如何编写特定的代码

以下是我如何实现搜索和突出显示单元格代码:

def findNmber(self):  # find the desire number and highlighten the cell
    if self.tabWidget.currentIndex() is 0:
            itemFound = False
            item = self.searchLoanNum.toPlainText()
            for rowIndex in range(self.inLoanTable.rowCount()):
                tbItem = self.inLoanTable.item(rowIndex,1)
                if tbItem.text() == item:
                   itemFound = True
                   self.inLoanTable.item(rowIndex,1).setBackground(QtGui.QColor(255,124,124))
            if itemFound == False:
                QMessageBox.warning(self,"Error","No Match",QMessageBox.Ok)
全班

class mainForm(QMainWindow,Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        QMainWindow.__init__(self, *args, **kwargs)
        self.setupUi(self)
        self.initUI()


    def initUI(self):
        self.search.clicked.connect(self.findNmber)
        self.search_2.clicked.connect(self.findNmber)

如果要捕获特定小部件外部发生的所有鼠标按钮事件,应在应用程序上安装事件过滤器,在鼠标按钮事件发生时进行检查,并确保该位置的小部件不是您要查找的小部件。
考虑到许多类使用子控件(QTable WIDGET是其中之一),因此需要通过父结构来确保单击的小部件不是所搜索的子项。
class mainForm(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        QtWidgets.QMainWindow.__init__(self, *args, **kwargs)
        self.setupUi(self)
        self.initUI()
        QtWidgets.QApplication.instance().installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.MouseButtonPress:
            # ensure that the source is a QWidget descendant, and it is in this window
            if (isinstance(source, QtWidgets.QWidget) and 
                source.window() == self and source != self.inLoanTable):
                    widget = QtWidgets.QApplication.widgetAt(event.globalPos())
                    while widget:
                        if widget == self.inLoanTable:
                            break
                        widget = widget.parent()
                    else:
                        # the widget or its parent(s) are not the table, proceed
                        self.resetBackgrounds()
        return super().eventFilter(source, event)

    def resetBackgrounds(self):
        model = self.inLoanTable.model()
        for row in range(self.inLoanTable.rowCount()):
            for column in range(self.inLoanTable.columnCount()):
                index = model.index(row, column)
                # check whether the index has a background set
                if index.data(QtCore.Qt.BackgroundRole):
                    # if it has, reset it
                    model.setData(index, None, QtCore.Qt.BackgroundRole)

        # clear the item selection
        self.inLoanTable.clearSelection()
一些重要的注释

  • 项目选择和突出显示是两件完全不同且不相关的事情;您和用户必须清楚这一点
  • 您试图实现的行为可能会让用户感到困惑:为什么单击其他位置会取消高亮显示单元格?它的目的是什么
  • 您没有使用任何布局管理器,所有小部件的几何图形都是固定的,这是几乎每次都应该避免的,原因有很多:例如,我的屏幕尺寸比您的UI小,我必须调整窗口大小,结果导致一些小部件不再可见。为主窗口设置主布局,并为容器小部件(如QTabWidget)使用子布局
  • 从您在评论中所写的内容来看,您似乎试图通过修改从
    pyuic
    生成的文件来实现您的程序,这是绝对不应该做的(您也不应该尝试模仿它的行为)。始终保持这些pyuic文件的完整性,并为主脚本使用单独的pyuic文件
  • 当我们询问一个最小的可复制示例时,我们的意思是我们需要能够复制、粘贴和运行它,并且可能进行最小的修改(如果没有修改);即使在修改之后,您的代码仍然很难复制,因为它缺少组件(例如,
    search_2
    ,本问题不需要这些组件,因此您不应该首先包含该连接)。如果你不帮助我们,我们就无法帮助你:不要“我认为它可以被复制和测试”:自己复制和测试它。这里的人们渴望帮助,但如果他们看不到足够的努力,也很容易感到厌烦:如果你不提供所需或要求的,他们中的许多人会继续,忽略你的问题,让你没有任何答案

您能否澄清“空白区域”的含义?在任何情况下,您的
findNumber
函数都不会选择该项,它只会更改其背景;项目选择(和突出显示)与设置项目背景完全不同。您的问题的答案可能会有很大的变化,因此请确切说明您想要做什么。很抱歉,我的描述很混乱。是的,我的findNumber不选择项目,它搜索特定文本并更改其背景颜色,这一个没有问题。我发布代码只是为了参考。空白是指主QtableWidget之外的区域。因此,当我填充CSV文件时,我可以选择任何单元格,它会将颜色变为蓝色,但我无法将其更改回原来的颜色。我希望在单击QTableWidget外部的区域时取消选择单元格(将其颜色更改为正常)。由于我有findNumber功能,它也会改变某些单元格的背景颜色(它会变成粉红色),我希望“单击空白区域”功能也能将我的“粉红色单元格”更改为正常。我想要这两个功能,但它们都需要通过“单击空白区域”功能来实现。我添加了我的GUI图片,希望它能通过点击空白区域“你的意思”点击表格外的任何地方“不客气!如果我的回答有助于解决您的问题,您应该单击左侧的复选标记将其标记为已接受。这将帮助人们找到你的问题,也会给你一些声誉分数,这对将来在这里的发展很有好处。为了将来的参考,我强烈建议您遵循MRE的指导原则,确保您的问题正确地集中在问题上,而不包括不必要的内容,并阅读好的问题。
class mainForm(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        QtWidgets.QMainWindow.__init__(self, *args, **kwargs)
        self.setupUi(self)
        self.initUI()
        QtWidgets.QApplication.instance().installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.MouseButtonPress:
            # ensure that the source is a QWidget descendant, and it is in this window
            if (isinstance(source, QtWidgets.QWidget) and 
                source.window() == self and source != self.inLoanTable):
                    widget = QtWidgets.QApplication.widgetAt(event.globalPos())
                    while widget:
                        if widget == self.inLoanTable:
                            break
                        widget = widget.parent()
                    else:
                        # the widget or its parent(s) are not the table, proceed
                        self.resetBackgrounds()
        return super().eventFilter(source, event)

    def resetBackgrounds(self):
        model = self.inLoanTable.model()
        for row in range(self.inLoanTable.rowCount()):
            for column in range(self.inLoanTable.columnCount()):
                index = model.index(row, column)
                # check whether the index has a background set
                if index.data(QtCore.Qt.BackgroundRole):
                    # if it has, reset it
                    model.setData(index, None, QtCore.Qt.BackgroundRole)

        # clear the item selection
        self.inLoanTable.clearSelection()