【发布时间】:2021-10-23 03:49:56
【问题描述】:
操作系统:W10。这可能很重要。如果您在不同的平台上得到不同的结果,反馈会很有帮助。
这是一个 MRE。如果您运行它并按 Ctrl+O,菜单标签将变为灰色。如果您通过单击“打开”按钮或使用其助记符 (Alt+O) 在QFileDialog 中选择一个文件,则打开文件对话框将关闭,“文件”和“帮助”菜单将变为非灰色。
但是,如果您再次按 Ctrl+O,这次在“文件名”框中输入文件名(QLineEdit),然后按回车键,对话框将关闭(选择成功) 但“文件”和“帮助”菜单仍然是灰色的。它看起来像这样:
import sys, os
from PyQt5 import QtWidgets, QtCore, QtGui
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Greying of menus MRE')
self.setGeometry(QtCore.QRect(100, 100, 400, 200))
menubar = QtWidgets.QMenuBar(self)
self.setMenuBar(menubar)
self.files_menu = QtWidgets.QMenu('&Files', self)
menubar.addMenu(self.files_menu)
self.help_menu = QtWidgets.QMenu('&Help', self)
menubar.addMenu(self.help_menu)
self.new_action = QtWidgets.QAction('&New', self)
self.files_menu.addAction(self.new_action)
self.open_action = QtWidgets.QAction('&Open', self)
self.files_menu.addAction(self.open_action)
self.open_action.setShortcut("Ctrl+O")
self.open_action.triggered.connect(self.open_file)
def focusInEvent(self, event ):
print('main_window focusInEvent')
super().focusInEvent(event)
def focusOutEvent(self, event ):
print('main_window focusOutEvent')
super().focusInEvent(event)
def activateWindow(self):
print('main_window activateWindow')
super().activateWindow()
def open_file(self):
print('open file')
main_window_self = self
# open_doc_dialog = QtWidgets.QFileDialog(self.get_main_window())
class OpenDocFileDialog(QtWidgets.QFileDialog):
def accepted(self):
print('accepted')
super().accepted()
def accept(self):
print('accept')
super().accept()
def close(self):
print('close')
super().close()
def done(self, r):
print(f'done r {r}')
# neither of these solves the problem:
# main_window_self.activateWindow()
# main_window_self.files_menu.activateWindow()
super().done(r)
def hide(self):
print(f'hide')
super().hide()
def focusInEvent(self, event ):
print('focusInEvent')
super().focusInEvent(event)
def focusOutEvent(self, event ):
print('focusOutEvent')
super().focusInEvent(event)
def activateWindow(self):
print('activateWindow')
super().activateWindow()
open_doc_dialog = OpenDocFileDialog(self)
open_doc_dialog.setWindowTitle('Choose file')
open_doc_dialog.setDirectory(os.getcwd())
# we cannot use the native dialog, because we need control over the UI
options = open_doc_dialog.Options(open_doc_dialog.DontUseNativeDialog)
open_doc_dialog.setOptions(options)
open_doc_button = open_doc_dialog.findChild(QtWidgets.QDialogButtonBox).button(QtWidgets.QDialogButtonBox.Open)
lineEdit = open_doc_dialog.findChild(QtWidgets.QLineEdit)
# this does not solve the problem
# lineEdit.returnPressed.disconnect()
# lineEdit.returnPressed.connect(open_doc_button.click)
print(f'open_doc_button {open_doc_button}, lineEdit {lineEdit}')
# show the dialog
dialog_code = open_doc_dialog.exec()
if dialog_code != QtWidgets.QDialog.Accepted: return
sel_files = open_doc_dialog.selectedFiles()
print(f'sel_files: {sel_files}')
app = QtWidgets.QApplication([])
main_window = MainWindow()
main_window.show()
sys.exit(app.exec())
这个问题可以理解,如果不解决,可以参考this answer。
请注意,此灰显并非禁用。正如上面链接中所解释的,这与菜单(或其标签)的“活动/非活动状态”有关。菜单始终处于启用状态,尽管在这种情况下,由于它是模态的,所以在显示打开文件对话框时不可能知道。在对话框消失后单击一个菜单,或者只是将鼠标悬停在它上面,就足以将它们都取消灰色...
据我了解,解释是“文件名”框QLineEdit 有一个信号returnPressed,它似乎激活了与使用“选择”时调用的插槽略有不同的东西按钮。你可以看到我已经尝试过尝试重新连接该信号,但无济于事。
QFileDialog 的方法done 似乎被调用,但是对话框关闭(不像close!),所以我尝试“激活”主窗口......然后是个人QMenus。 .. 不起作用。
我不清楚如何处理这种“活动状态”业务,或者为什么连接到returnPressed 的插槽(似乎)无法在另一个插槽设法将“活动状态”返回菜单时这样做。
编辑
搜索 Musicamante 的“未抛光”建议让我想到了这一点:
lineEdit.returnPressed.disconnect()
def return_pressed():
style = main_window_self.menubar.style()
style.unpolish(main_window_self.menubar)
open_doc_button.click()
lineEdit.returnPressed.connect(return_pressed)
...不幸的是,这不起作用。
【问题讨论】:
-
链接的问题似乎并不完全相关,因为问题与非阻塞对话框有关(这是设计上的正确行为)。您能否确认 QFileDialog 的静态方法也有相同的行为,无论是原生的还是非原生的?同时,作为一种解决方法,您可以在对话框关闭后立即取消抛光,从而强制重新绘制菜单栏。
-
谢谢。本机文件选择器不会出现此问题。我只是说另一个问题是相关的,如果没有找到它,我仍然会更加摸不着头脑,因为我还没有听说过
QWidget的这种“活动/非活动状态”。你能解释一下你所说的“不抛光”技术是什么意思吗?也许您可以将其作为答案? -
@mikerodent 我似乎无法在 linux 上重现这个,但我可能误解了这个问题。据我所知,问题是当对话框关闭时主窗口仍然处于非活动状态。但它是真的不活跃,还是只是看起来那样?也就是说,您是否可以在关闭对话框后立即使用仅键盘与窗口进行交互,还是只是窗口没有正确重绘?
-
啊,也许是另一个Windoze“奇点”。是的,这完全是关于外表!键盘交互工作正常,实际上在对话框关闭后按 Alt-F 不仅显示“文件”菜单的菜单项,而且“重新激活”两个菜单的标签。 PS 抱歉缺少导入:将修改!
-
看起来像一个错误,那么。如果您要尝试强制重新绘制的解决方法,您可能需要等到事件循环将控制权返回给主窗口。 single-shot timer 稍有延迟就可以解决问题。
标签: python user-interface pyqt5 windows-10 qfiledialog