1

NB 操作系统是W10

这里的上下文是 pytest-qt。我找到了这个答案并尝试使用它(见下文)。

当测试方法调用创建 aQFileDialog然后调用exec它的应用程序方法时,我收到此错误。然后控制台发出此消息并且控制台挂起。我别无选择,只能手动关闭控制台。

这里涉及的一个因素是此设置(在运行测试之前的测试期间设置):

os.environ['QT_QPA_PLATFORM'] = 'offscreen'

... 如果没有此行,则QFileDialog显示 OK exec,测试结束,并且控制台不会挂起。

我当然不知道哪个插件是罪魁祸首......在“propagateSizeHints”上搜索了一下,没有任何结果。pip freeze输出如下:

atomicwrites==1.4.0
attrs==21.2.0
colorama==0.4.4
coloredlogs==15.0.1
concurrent-log-handler==0.9.19
humanfriendly==10.0
iniconfig==1.1.1
packaging==21.2
pluggy==1.0.0
portalocker==2.3.2
py==1.11.0
pyparsing==2.4.7
PyQt5==5.15.6
PyQt5-Qt5==5.15.2
PyQt5-sip==12.9.0
pyreadline3==3.3
pytest==6.2.5
pytest-qt==4.0.2
pywin32==302
toml==0.10.2

在搜索问题后,exec我找到了 eyllanesc 的上述答案。所以我尝试了这个:

def test_file_dialog_should_do_x(request, qtbot):
    t_logger.info(f'\n>>>>>> test name: {request.node.originalname}')
    main_win = main_window.AutoTransMainWindow() 
    proj = project.Project(main_win)
    def on_timeout():
        proj.modify_working_files()
        print('A1')
        assert proj.file_dlg.windowTitle() == 'Nonsense'
        print('A2')
    print('A3')
    QtCore.QTimer.singleShot(0, on_timeout)
    print('A4')
    assert proj.file_dlg.windowTitle() == 'Nonsense'

(这些断言注定要失败)

应用程序代码尽可能简单:

def modify_working_files(self):
    self.file_dlg = QtWidgets.QFileDialog()
    self.file_dlg.exec()

...但我再次收到相同的“此插件不...”消息,控制台再次挂起。只有“A3”和“A4”被打印出来。

一种解决方案可能只是exec普遍模拟。但是 eyllanesc 知道他的洋葱,如果是这样的话,大概会这么说。如果是这种情况,我看不出如何进行任何由qtbot.

到目前为止,我对“屏幕外”设置没有任何问题。但也许有限制......这篇文章似乎表明这可能是问题的根源。

MRE:

import os

from PyQt5 import QtWidgets, QtCore, QtGui

os.environ['QT_QPA_PLATFORM'] = 'offscreen'

QtWidgets.QApplication([])

class MainWin(QtWidgets.QMainWindow):
    pass

class Project():
    def __init__(self, main_win):
        self.main_win = main_win
        
    def modify_working_files(self):
        self.file_dlg = QtWidgets.QFileDialog()
        self.file_dlg.exec()        
        
        
def test_file_dialog_should_do_x(request, qtbot):
    print(f'\n>>>>>> test name: {request.node.originalname}')
    
    main_win = MainWin() 
    proj = Project(main_win)
    def on_timeout():
        proj.modify_working_files()
        print('A1')
        assert proj.file_dlg.windowTitle() == 'Nonsense'
        print('A2')
    print('A3')
    QtCore.QTimer.singleShot(0, on_timeout)
    print('A4')
    assert proj.file_dlg.windowTitle() == 'Nonsense'

on_timeout在我的机器上,如果 QT_QPA_PLATFORM 行被注释掉,这会在函数行中产生(如预期的那样)FAIL 。

如果后者没有被注释掉,我会收到插件错误消息并且控制台挂起。

即使MainWinshow()在其构造函数中进行,即使QFileDialog是使用创建QtWidgets.QFileDialog(self.main_win),错误仍然会发生。

我也尝试过class Project(object),甚至 (longshot) class Project(QtCore.QObject)。没有喜悦。

注意,我还在我的虚拟环境中的所有文件以及我的核心 Python 安装(v. 3.9.4)中的所有文件中搜索了字符串“propagatesize”。没有什么!

4

1 回答 1

1

此消息的来源似乎在这里

void QPlatformWindow::propagateSizeHints() {qWarning("This plugin does not support propagateSizeHints()"); }

所以这是关于在 Windows 平台上使用 PyQt5(或 Qt5)。从我的实验中可以看出,这是一种症状,而不是所指出的失败的原因。不幸的是,这个旨在列出“所有 Qt5 类”(不仅仅是 PyQt5)的页面不包括它。

这里,可以通过将其放入由所有测试文件导入的文件中来抑制此特定消息:

def qt_message_handler(mode, context, message):
    if mode == QtCore.QtInfoMsg:
        mode = 'INFO'
    elif mode == QtCore.QtWarningMsg:
        mode = 'WARNING'
        if 'propagateSizeHints' in message:
            return
    elif mode == QtCore.QtCriticalMsg:
        mode = 'CRITICAL'
    elif mode == QtCore.QtFatalMsg:
        mode = 'FATAL'
    else:
        mode = 'DEBUG'
    print('qt_message_handler: line: %d, func: %s(), file: %s' % (
          context.line, context.function, context.file))
    print('  %s: %s\n' % (mode, message))

QtCore.qInstallMessageHandler(qt_message_handler)

为了克服 的问题exec,以下算作一种解决方法。我从 Qt5 文档中注意到:

QDialog.exec()

注意:避免使用此功能;相反,使用 open()。与 exec() 不同,open() 是异步的,并且不会旋转额外的事件循环。这可以防止发生一系列危险的错误(例如,在通过 exec() 打开对话框时删除对话框的父级)。使用 open() 时,您可以连接到 QDialog 的 finished() 信号,以便在对话框关闭时得到通知。

交换这个,我仍然收到消息“这个插件不支持propagateSizeHints()”......但控制台没有挂起。

exec()返回一个int值,但open不返回。克服这一点需要付出很小的代价。

但是......事实上,在我的机器上,open总是会导致一个非模态对话框,即使我setModal(True)(在它之前)。

幸运的是show()荣誉setModal(...)......并且也不会导致控制台崩溃。好像用的那个。

于 2021-11-12T12:02:44.017 回答