在更新期间显示图像(如演示文稿)而不显示桌面
Posted
技术标签:
【中文标题】在更新期间显示图像(如演示文稿)而不显示桌面【英文标题】:Displaying images like a presentation without showing the desktop during update 【发布时间】:2017-02-13 09:30:18 【问题描述】:我正在尝试使用 Xubuntu 14.04 下的以下 Python 代码在我的辅助显示器上连续显示存储在 ./pics 目录下的图像。
from PyQt4 import QtCore, QtGui
import sys
import os
import multiprocessing as mp
import time
def displayImage( impath ):
app = QtGui.QApplication(sys.argv)
window = QtGui.QMainWindow()
# Select monitor
screenres = QtGui.QApplication.desktop().screenGeometry(1);
window.move(QtCore.QPoint(screenres.x(), screenres.y()))
window.resize(screenres.width(), screenres.height())
# Set the image to be shown
pic = QtGui.QLabel(window)
pic.setGeometry(0, 0, 1960, 1080)
pic.setPixmap(QtGui.QPixmap( impath ))
window.showFullScreen()
app.exec_()
return
def controller( imdir ):
# List the contents of the directory
im_paths = os.listdir( imdir )
# Keep only image files
pc = list(im_paths)
for p in pc:
print p
if not p.split('.')[-1] in [ 'jpg', 'JPG', 'png', 'PNG' ]:
im_paths.remove( p )
if not im_paths:
return 1
# Start showing the images by calling project function as a new process (multiprocessing module)
for f in im_paths:
print 'Showing image:', p, '...'
# Run project process
p = mp.Process( target=displayImage, args=( imdir+f, ) )
p.start()
# Keep dispaying image for 3 seconds
time.sleep(2)
p.terminate()
return 0
if __name__ == '__main__':
controller( './pics/' )
exit(0)
问题
显示图像A的进程终止有一段时间,直到进程结束 显示图像 B 出现在应用程序不显示任何内容的地方,并且有一段时间呈现桌面破坏了用户体验。
任何想法如何使用 Qt4 连续显示图像?
附言。可能会接受涉及 matplotlib 和/或 opencv 的答案,但我认为直接的路径是通过 Qt。
【问题讨论】:
只是一个问题:为什么要为显示的每张图像启动一个新的 QApplication,而不是只启动一个而不只是更新Pixmap
中的图像?正确初始化需要时间。然后当你已经显示一个图像时,创建一个新的QPixmap
并在x
秒后使用QPixmap.swap
切换?
嗨!我对 Qt 没有经验,所以我无法想象最佳解决方案是什么。你的回答似乎是个好主意!所以,我正在努力。您能否提供一个使用 QPixmap.swap 方法的示例?
【参考方案1】:
最后,我想出了解决方案。 alexblae 认为不应在每次图像更新时重新启动 qt 应用程序的想法是关键点。但首先...我必须详细了解 Qt 框架的体系结构,一个类如何从另一个类继承以及如何生成和处理事件。
让我引用更新后的代码,以便其他用户在遇到类似问题时查看并获得优势。
from PyQt4 import QtCore, QtGui
import multiprocessing as mp
import sys
import os
import time
class Pic( QtGui.QLabel ):
def __init__( self, w, im_paths ):
QtGui.QLabel.__init__(self,w)
self.ims = im_paths
# Set the first image that will be displayed
self.setPixmap(QtGui.QPixmap( self.ims[0] ) )
self.i = 1
# Catch timer events. On each event display the next image
def timerEvent(self):
# Update the displayed image
self.setPixmap(QtGui.QPixmap( self.ims[self.i] ) )
self.i = ( self.i + 1 ) % len( self.ims )
def displayImages( im_paths ):
app = QtGui.QApplication(sys.argv)
window = QtGui.QMainWindow()
screenres = QtGui.QApplication.desktop().screenGeometry(1);
window.move(QtCore.QPoint(screenres.x(), screenres.y()))
window.resize(screenres.width(), screenres.height())
pic = Pic(window, im_paths)
pic.setGeometry(0, 0, 1960, 1080)
window.showFullScreen()
# Generate a timerEvent every 1 second. On each second the handler of
# the event updates the displayed image
timer = QtCore.QTimer()
timer.timeout.connect(pic.timerEvent)
timer.start(1000) #1 second
sys.exit(app.exec_())
def controller( imdir ):
# List the contents of the directory
im_paths = sorted( os.listdir( imdir ) )
for i, path in enumerate( im_paths ):
im_paths[i] = imdir + '/' + path
# Keep only image files
pc = list(im_paths)
for p in pc:
if not p.split('.')[-1] in [ 'jpg', 'JPG', 'png', 'PNG' ]:
im_paths.remove( p )
if not im_paths:
return 1
# Run project process
p = mp.Process( target=displayImages, args=( im_paths, ) )
p.start()
# Keep displaying images for 1 minute
time.sleep(5)
p.terminate()
return 0
if __name__ == '__main__':
controller( './pics/' )
exit(0)
Pic 类继承自 QLabel,以便定义 timerEvent 方法。使用计时器事件,我们能够通知 qt 应用程序何时更新显示的图像。
另外,请注意,多处理模块的使用似乎有点矫枉过正。有人可能会直接调用 displayImages 函数。
【讨论】:
这是特定于 Linux 系统的吗? 不,代码可以在Linux和Windows系统上执行。唯一的依赖是 Qt 框架。【参考方案2】:我有一个使用 OpenCV 和 python 的解决方案。
下面是代码和解释:
import cv2 # for read/display images
import glob # for linking to image file (.jpg)
#--- following is the directory containing my images of jpg format ---
jpg_files=glob.glob("C:/Users/Desktop/Stack/*.jpg")
#--- Here I run through every image file, read it and then display it with a lapse time of 1 second ---
for img_no in range(len(jpg_files)):
x = jpg_files[img_no]
img = cv2.imread(x,1)
cv2.imshow('BINGO.jpg',img)
cv2.waitKey(1000)
cv2.destroyAllWindows()
希望这会有所帮助 :D
【讨论】:
嗨耶鲁!感谢你付出的努力!由于缺乏特定要求,该解决方案不太适合,该解决方案应涵盖:a) 没有窗口装饰器的全屏模式和 b) 选择特定显示器的能力。 嗯,很高兴我能提供一些见解。请检查cv2.namedWindow()
的功能。它可能会有所帮助。
如果遇到一个解决方案,请发布:)
刚刚添加了解决方案。以上是关于在更新期间显示图像(如演示文稿)而不显示桌面的主要内容,如果未能解决你的问题,请参考以下文章
ppt打不开,显示发现文件中的内容有问题。可尝试修复此演示文稿