如何让PyQt5的QListWidget仅在选中项时显示ToolTip?
实现QListWidget仅选中项显示ToolTip
要实现仅在选中列表项时显示ToolTip,需要修改原有的ToolTip触发逻辑,放弃鼠标进入项时设置ToolTip的方式,改为在ToolTip事件中判断当前项是否选中,再决定是否显示。以下是修改后的完整代码及关键说明:
修改后的完整代码
import serial, time, sys import serial.tools.list_ports from PyQt5 import QtGui, QtWidgets, QtCore import json, time class GUI(QtWidgets.QWidget): def __init__(self): super().__init__() self.__init_ui() def closeEvent(self, event): super().closeEvent(event) def __init_ui(self): self.setWindowTitle('QListWidgetToolTipDemo') self.history_log = HistoryList() self.history_log.itemDoubleClicked.connect(self.history_item_selected) self.history_log.returnPressed.connect(self.history_item_selected) # 统一选择模式,避免与HistoryList内部设置冲突 # self.history_log.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) self.line_edit = QtWidgets.QLineEdit() self.line_edit.returnPressed.connect(self.populate_history) self.middle_layout = QtWidgets.QHBoxLayout() self.middle_layout.addWidget(self.history_log) self.middle_layout.addWidget(self.line_edit) middle_layout_wrapper = QtWidgets.QWidget() middle_layout_wrapper.setLayout(self.middle_layout) middle_layout_wrapper.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) # 设置整体GUI布局 gui_layout = QtWidgets.QVBoxLayout() gui_layout.addWidget(middle_layout_wrapper) gui_layout.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) gui_layout.setContentsMargins(QtCore.QMargins(0, 0, 0, 0)) self.setLayout(gui_layout) def populate_history(self): self.history_log.addItem(self.line_edit.text()) self.line_edit.clear() def history_item_selected(self): self.line_edit.setText(self.history_log.currentItem().text()) class HistoryList(QtWidgets.QListWidget): returnPressed = QtCore.pyqtSignal() def __init__(self) -> None: super().__init__() self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection) # 移除鼠标跟踪和itemEntered信号连接,不再通过鼠标进入触发ToolTip # self.setMouseTracking(True) # self.itemEntered.connect(self.__showToolTip) def keyPressEvent(self, ev): super().keyPressEvent(ev) if ev.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return): self.returnPressed.emit() def addItem(self, aitem) -> None: item = '' text = '' if isinstance(aitem, str): item = QtWidgets.QListWidgetItem() text = aitem item.setText(text) elif isinstance(aitem, QtWidgets.QListWidgetItem): item = aitem text = item.text() # 移除不必要的空widget设置,避免干扰项的默认行为 # self.setItemWidget(item, QtWidgets.QWidget()) super().addItem(item) def viewportEvent(self, event): # 捕获ToolTip事件 if event.type() == QtCore.QEvent.ToolTip: # 获取鼠标在列表视口内的位置 pos = event.pos() # 获取该位置对应的列表项 item = self.itemAt(pos) if item and item.isSelected(): # 生成ToolTip内容 text = item.text() info = {"time": str(time.time()), "entry": text} info_str = json.dumps(info, indent=4) # 在鼠标全局位置显示ToolTip QtWidgets.QToolTip.showText(event.globalPos(), info_str, self) return True else: # 非选中项,隐藏ToolTip QtWidgets.QToolTip.hideText() return True # 其他事件交给父类处理 return super().viewportEvent(event) if __name__ == "__main__": app = QtWidgets.QApplication([]) console = GUI() screensize = app.desktop().availableGeometry().size() console.show() exit(app.exec_())
关键修改说明
- 移除鼠标跟踪与itemEntered连接:原代码通过鼠标进入项的事件设置ToolTip,导致所有悬停项都显示ToolTip,现在移除这部分逻辑。
- 重写viewportEvent处理ToolTip事件:
- 捕获
QEvent.ToolTip事件,获取鼠标位置对应的列表项。 - 仅当项处于选中状态时,生成并显示ToolTip;否则直接隐藏ToolTip。
- 捕获
- 清理冗余代码:移除
addItem中不必要的空widget设置,避免干扰列表项的默认绘制。 - 统一选择模式:注释掉GUI类中重复设置的选择模式,避免与HistoryList内部的设置冲突。
内容的提问来源于stack exchange,提问作者kyrlon
相关产品推荐
相关产品推荐

