首页 > 解决方案 > 单击空白区域时禁用选择/背景颜色

问题描述

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

我知道我需要使用 MousePressEvent,逻辑是

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)
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1303, 972)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(50, 10, 1201, 931))
        self.tabWidget.setLayoutDirection(QtCore.Qt.LeftToRight)
        self.tabWidget.setTabPosition(QtWidgets.QTabWidget.South)
        self.tabWidget.setTabShape(QtWidgets.QTabWidget.Rounded)
        self.tabWidget.setUsesScrollButtons(False)
        self.tabWidget.setObjectName("tabWidget")
        self.inLons = QtWidgets.QWidget()
        self.inLons.setObjectName("inLons")
        self.searchLoanNum = QtWidgets.QTextEdit(self.inLons)
        self.searchLoanNum.setGeometry(QtCore.QRect(980, 10, 141, 31))
        self.searchLoanNum.setObjectName("searchLoanNum")
        self.search = QtWidgets.QPushButton(self.inLons)
        self.search.setGeometry(QtCore.QRect(1120, 10, 71, 31))
        self.search.setObjectName("search")
        self.loanNumberS = QtWidgets.QLabel(self.inLons)
        self.loanNumberS.setGeometry(QtCore.QRect(930, 10, 41, 31))
        self.loanNumberS.setObjectName("loanNumberS")
        self.save = QtWidgets.QPushButton(self.inLons)
        self.save.setGeometry(QtCore.QRect(970, 860, 101, 41))
        self.save.setObjectName("save")
        self.exit = QtWidgets.QPushButton(self.inLons)
        self.exit.setGeometry(QtCore.QRect(1080, 860, 101, 41))
        self.exit.setObjectName("exit")
        self.createNewColumn_1 = QtWidgets.QPushButton(self.inLons)
        self.createNewColumn_1.setGeometry(QtCore.QRect(20, 20, 161, 41))
        self.createNewColumn_1.setObjectName("createNewColumn_1")
        self.createNewLoan = QtWidgets.QPushButton(self.inLons)
        self.createNewLoan.setGeometry(QtCore.QRect(190, 20, 161, 41))
        self.createNewLoan.setObjectName("createNewLoan")
        self.openFile = QtWidgets.QPushButton(self.inLons)
        self.openFile.setGeometry(QtCore.QRect(360, 20, 161, 41))
        self.openFile.setObjectName("openFile")
        self.generateNum = QtWidgets.QPushButton(self.inLons)
        self.generateNum.setGeometry(QtCore.QRect(530, 20, 161, 41))
        self.generateNum.setObjectName("generateNum")
        self.inLoanTable = QtWidgets.QTableWidget(self.inLons)
        self.inLoanTable.setGeometry(QtCore.QRect(10, 70, 1171, 781))
        self.inLoanTable.setObjectName("inLoanTable")
        self.inLoanTable.setColumnCount(0)
        self.inLoanTable.setRowCount(0)
        self.tabWidget.addTab(self.inLons, "")
       
     def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Herbarium Assistant"))
        self.search.setText(_translate("MainWindow", "Search"))
        self.loanNumberS.setText(_translate("MainWindow", "Loan #"))
        self.save.setText(_translate("MainWindow", "Save"))
        self.exit.setText(_translate("MainWindow", "Exit"))
        self.createNewColumn_1.setText(_translate("MainWindow", "create a new column"))
        self.createNewLoan.setText(_translate("MainWindow", "create a new loan"))
        self.openFile.setText(_translate("MainWindow", "open file"))
        self.generateNum.setText(_translate("MainWindow", "generate #"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.inLons), _translate("MainWindow", "IN-LOANS"))
        self.createNewColumn_2.setText(_translate("MainWindow", "create a new column"))
        self.createNewGift.setText(_translate("MainWindow", "create a new gift"))
        self.openFile_2.setText(_translate("MainWindow", "open file"))
        self.generateNum_2.setText(_translate("MainWindow", "generate #"))
        self.giftNumS.setText(_translate("MainWindow", "Gift #"))
        self.search_2.setText(_translate("MainWindow", "Search"))
        self.save_2.setText(_translate("MainWindow", "Save"))
        self.exit_2.setText(_translate("MainWindow", "Exit"))

标签: pythonpyqt5

解决方案


如果您想捕获在特定小部件之外发生的所有鼠标按钮事件,您应该在应用程序上安装一个事件过滤器,检查鼠标按钮事件何时发生,并确保该位置的小部件不是您要查找的小部件。
考虑到许多类使用子小部件(QTableWidget 就是其中之一),因此您需要遍历父结构以确保单击的小部件不是您正在搜索的小部件的子级。

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 文件完好无损,并为您的主脚本使用单独的文件。
  • 当询问一个最小的可重现示例时,我们的意思是我们需要能够复制、粘贴并运行它,并且可能只进行最少的(如果没有)修改;即使在您修改之后,您的代码仍然难以重现,因为它缺少组件(例如,search_2对于这个问题来说,不需要它,因此您不应该首先包含该连接)。如果您不帮助我们,我们也无法帮助您:不要“我认为可以复制和测试”:您自己复制和测试。这里的人们渴望提供帮助,但如果他们没有看到足够的努力,他们也很容易感到无聊:如果您不提供所需或要求的内容,他们中的许多人会继续前进,忽略您的问题,让您没有任何答案。

推荐阅读