【发布时间】:2019-11-19 05:09:49
【问题描述】:
如何使用 PyQt5/PySide 或任何其他 Python 库以全屏模式在辅助显示器上显示所需的图像?过去,我使用帧缓冲图像查看器(Fbi 和 Fbi improved)。但是,这种方法需要我使用 Linux。我更喜欢在 Windows 中工作,最好使用 Python 找到解决方案。
动机/背景
我正在研究基于 DLP 投影的 3D 打印流程。当我使用 HDMI 将 DLP 投影仪连接到我的 Windows PC 时,它显示为第二台显示器。我只想将这个辅助显示器 (DLP) 用于显示我想要的 3D 打印过程的图案图像(png、bmp 或 svg)。我想使用 Python 以编程方式控制正在显示的图像。 这是https://3dprinting.stackexchange.com/questions/1217/how-to-display-images-on-dlp-using-hdmi-for-3d-printing 的后续问题
部分解决方案和问题
下面的代码是一种可能的解决方案,但我不确定它是正确的还是最有效的方法。我发现了两种使用 PyQt5 的方法:1)使用闪屏,2)使用 QLabel。我的代码面临以下问题:
- 光标按预期隐藏,但是如果我不小心在辅助屏幕上单击鼠标,则启动屏幕会关闭。
- 如果我使用 QLabel 方法,我会看到出现白屏,然后我的图像被加载。从出现白屏到显示实际图像之间存在约 0.5-1 秒的明显延迟。
- 如果图像以高频率显示(例如:每 1 秒),则此代码无法正常工作。例如,在代码中将 total_loops=1 更改为 total_loops=25。使用启动画面方法时,我看到启动画面出现在主屏幕上,然后它移动到辅助屏幕。使用 QLabel 方法时,我看到的只是出现白屏,并且仅显示图像的最后一次迭代。此外,QLabel 的窗口在主屏幕上变为活动状态,并且在任务栏中可见。
- 如果我想显示视频而不是图像,我该如何处理?
对于3D打印应用,解决方案需要满足以下要求:
- 辅助屏幕是 DLP 投影仪,它不应包含任何与操作系统相关的窗口/任务栏/等...
- 辅助屏幕上不应出现光标/鼠标或其他应用程序
- 图片/视频需要全屏显示
- 在副屏显示或更新图像时,主屏应无干扰。例如,辅助屏幕中的图像窗口不应将焦点从主屏幕中的当前活动窗口移开
import time
start_time = time.time()
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QSplashScreen
from PyQt5.QtGui import QPixmap, QCursor
from PyQt5.QtCore import Qt
import os
app = QApplication(sys.argv)
total_loops = 1
for i in range(total_loops):
# https://doc.qt.io/qtforpython/index.html
# https://www.riverbankcomputing.com/static/Docs/PyQt5/module_index.html
s = app.screens()[1] # Get the secondary screen
# Display info about secondary screen
print('Screen Name: {} Size: {}x{} Available geometry {}x{} '.format(s.name(), s.size().width(), s.size().height(), s.availableGeometry().width(), s.availableGeometry().height()))
# Hide cursor from appearing on screen
app.setOverrideCursor(QCursor(Qt.BlankCursor)) # https://forum.qt.io/topic/49877/hide-cursor
# Select desired image to be displayed
pixmap = QPixmap('test.png')
# Splash screen approach
# https://doc.qt.io/qtforpython/PySide2/QtWidgets/QSplashScreen.html?highlight=windowflags
splash = QSplashScreen(pixmap) # Set the splash screen to desired image
splash.show() # Show the splash screen
splash.windowHandle().setScreen(s) # Set splash screen to secondary monitor https://stackoverflow.com/a/30597458/4988010
splash.showFullScreen() # Show in splash screen in full screen mode
# # Qlabel apporach
# l = QLabel()
# l.setPixmap(pixmap)
# l.move(1920,0)
# l.show()
# l.windowHandle().setScreen(s) # https://stackoverflow.com/a/30597458/4988010
# l.showFullScreen()
time.sleep(0.5)
end_time = time.time()
print('Execution time: ', end_time-start_time )
sys.exit(app.exec_())
【问题讨论】:
-
你使用的for循环不可能工作,因为它会阻塞qt的事件处理。
time.sleep也将被阻止。在循环内不断地重新创建窗口是一个非常糟糕的主意,而且完全没有必要。使用QSplashSctreen也没什么意义,它不太适合您的用例。我建议您摆脱 for 循环,最初专注于全屏显示单个图像,该图像不会响应用户交互。 (与其他应用程序、任务栏等相关的问题对于 SO 来说是题外话,因为它们与编程无关,本身)。 -
有很多window attributes和window flags可以用来控制qt窗口的行为。平台之间的确切行为通常可能有很大差异,因此您可能需要进行一些试验。 (PS:你瞄准的基本设计和kiosk mode很像)。
标签: python pyqt pyside framebuffer 3d-printing