简体   繁体   English

运行应用程序并在 PyQt5 上渲染后退出

[英]Run an application and quit it after rendering on PyQt5

I would like to render SVG files with PyQt5.我想用 PyQt5 渲染 SVG 文件。

The simplest way to do that is to use QSvgGenerator applied on a QPainter object.最简单的方法是使用应用于 QPainter 对象的 QSvgGenerator。

However, for some reason I have to render text in the output SVG file.但是,出于某种原因,我必须在输出 SVG 文件中呈现文本。 To do that, having a QApplication running is compulsory because some components initialized during the execution of QApplication are needed.为此,必须运行 QApplication,因为需要在执行 QApplication 期间初始化一些组件。 Otherwise, QPainter.drawText() methods end in a SEGFAULT.否则, QPainter.drawText()方法以 SEGFAULT 结尾。

I'm now able to generate text in my SVG file by creating a QSvgWidget object with handles the painting through the paintEvent method.我现在可以通过创建一个 QSvgWidget 对象来在我的 SVG 文件中生成文本,该对象通过paintEvent方法处理绘画。

If I just run the application with the exec_ method, everything works fine.如果我只是使用exec_方法运行应用程序,则一切正常。 However I'm only interested in generating the SVG, so I don't want to be forced to close the main window with my mouse (I'd like to run my program on a headless server).但是我只对生成 SVG 感兴趣,所以我不想被迫用鼠标关闭主窗口(我想在无头服务器上运行我的程序)。 Here is my base code:这是我的基本代码:

app = QApplication(sys.argv)
drawer = MyDrawerClass()
drawer.show()
app.exec_()

and MyDrawerClass inheritates from QSvgWidget and implements printEvent method which is successfully called when executing the app. MyDrawerClass继承自QSvgWidget并实现了在执行应用程序时成功调用的printEvent方法。

So my question is: Is there a way to run the app a headless way and quit it after everything is rendered?所以我的问题是:有没有办法以无头方式运行应用程序并在渲染完所有内容后退出? I read a few things on QTimer but I can't find any example which suits my usage.我在QTimer上阅读了一些内容,但找不到任何适合我使用的示例。

I assume you're referring to the approach used in your previous question .我假设您指的是上一个问题中使用的方法。

Some painter capabilities require that a QGuiApplication is constructed before using them, and drawing text is amongst them, since it depends on the system's own GUI management (default fonts, DPI, etc).一些画家功能需要在使用它们之前构造一个 QGuiApplication ,并且绘制文本也在其中,因为它取决于系统自己的 GUI 管理(默认字体、DPI 等)。 Usually one would use a standard QApplication, but, as reported in the documentation :通常人们会使用标准的 QApplication,但是,正如文档中所报告的那样:

For "non-QWidget based Qt applications, use QGuiApplication instead, as it does not depend on the QtWidgets library".对于“非基于 QWidget 的 Qt 应用程序,请改用 QGuiApplication,因为它不依赖于 QtWidgets 库”。

This will make the creation of a QGuiApplication faster and lighter.这将使 QGuiApplication 的创建更快更轻。

Unfortunately, a running display is mandatory for Q[Gui]Applications, so you will not be able to run it on a headless server, unless at least a minimal virtual X server is active.不幸的是,对于 Q[Gui]Applications 来说,运行显示是强制性的,因此您将无法在无头服务器上运行它,除非至少有一个最小的虚拟 X 服务器处于活动状态。 If you can manage to do that, the following example should work fine.如果你能做到这一点,下面的例子应该可以正常工作。

def createImage(width=400, height=400):
    rect = QRect(0, 0, width, height)
    generator = QSvgGenerator()
    generator.setFileName("test.svg")
    generator.setSize(rect.size())
    generator.setViewBox(rect)
    painter = QPainter(generator)
    painter.fillRect(rect, Qt.black)
    textRect = QRect(0, 0, 200, 200)
    textRect.moveCenter(rect.center())
    painter.setPen(Qt.white)
    painter.setBrush(Qt.darkGray)
    painter.drawRect(textRect)
    painter.drawText(textRect, Qt.AlignCenter, 'test')
    painter.end()

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    createImage()

Since there's no need for an event loop (because there's no GUI interaction), you don't have to actually exec_() , and the program will automatically exit as soon as the paint function is returned.由于不需要事件循环(因为没有 GUI 交互),因此您实际上exec_() ,并且一旦返回绘制函数,程序就会自动退出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM