python-3.x - 当按钮单击时在目录中显示下一个图像
问题描述
我正在尝试在 Python 中创建一个程序,该程序允许在 MainWin 中加载图像,然后允许通过单击“下一步”来更改图像,从而在文件夹中显示下一个图像。当 Next 到达文件夹中文件的末尾时,它应该跳转到文件夹的开头。我设法加载图像,甚至用 Next 更改图像,但只更改一次 - 如果我再次单击 Next,图片不再更改。知道为什么吗?谢谢
self.LoadImage.clicked.connect(self.LoadImg)
self.NextImage.clicked.connect(self.NextImg)
def LoadImg(self):
global directory
global filename
directory = 'C:/Users/mario/Desktop/desktop 17112019 2/New Folder'
filename, _ = QtWidgets.QFileDialog.getOpenFileName(None, 'Select Image', directory, 'Image Files (*.png *.jpg *.jpeg)')
if filename: # If the user gives a file
pixmap = QtGui.QPixmap(filename) # Setup pixmap with the provided image
pixmap = pixmap.scaled(self.label.width(), self.label.height(),
QtCore.Qt.KeepAspectRatio) # Scale pixmap
self.label.setPixmap(pixmap) # Set the pixmap onto the label
self.label.setAlignment(QtCore.Qt.AlignCenter) # Align the label to center
def vec(self):
a = os.listdir(directory)
k = a.index(os.path.basename(filename))
imageList = a[k:] + a[:k]
return imageList
def NextImg(self):
pool = itertools.cycle(self.vec())
print(next(pool))
pixmap = QtGui.QPixmap(directory + '/' + next(pool)) # Setup pixmap with the provided image
pixmap = pixmap.scaled(self.label.width(), self.label.height(), QtCore.Qt.KeepAspectRatio)
self.label.setPixmap(pixmap) # Set the pixmap onto the label
self.label.setAlignment(QtCore.Qt.AlignCenter) # Align the label to center
编辑:我怀疑我需要断开所选文件与 LoadImage 和循环迭代器之间的连接,但不知道如何。
解决方案
首先,你不应该使用全局变量,尤其是敏感的和“通用”的名字,比如directory
. 我还建议您永远不要对函数和变量使用大写的名称。
要跟踪当前文件并循环浏览目录的内容,请改用类属性。
在此示例中,我使用从所选文件目录的内容开始的 python 迭代器,每次按下“下一步”按钮时,都会加载迭代器的下一项,如果迭代器已到达其末尾,它将生成一个新的。
from PyQt5 import QtCore, QtGui, QtWidgets
class ImageLoader(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
layout = QtWidgets.QGridLayout(self)
self.label = QtWidgets.QLabel()
layout.addWidget(self.label, 0, 0, 1, 2)
self.label.setMinimumSize(200, 200)
# the label alignment property is always maintained even when the contents
# change, so there is no need to set it each time
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.loadImageButton = QtWidgets.QPushButton('Load image')
layout.addWidget(self.loadImageButton, 1, 0)
self.nextImageButton = QtWidgets.QPushButton('Next image')
layout.addWidget(self.nextImageButton)
self.loadImageButton.clicked.connect(self.loadImage)
self.nextImageButton.clicked.connect(self.nextImage)
self.dirIterator = None
self.fileList = []
def loadImage(self):
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self, 'Select Image', '', 'Image Files (*.png *.jpg *.jpeg)')
if filename:
pixmap = QtGui.QPixmap(filename).scaled(self.label.size(),
QtCore.Qt.KeepAspectRatio)
if pixmap.isNull():
return
self.label.setPixmap(pixmap)
dirpath = os.path.dirname(filename)
self.fileList = []
for f in os.listdir(dirpath):
fpath = os.path.join(dirpath, f)
if os.path.isfile(fpath) and f.endswith(('.png', '.jpg', '.jpeg')):
self.fileList.append(fpath)
self.fileList.sort()
self.dirIterator = iter(self.fileList)
while True:
# cycle through the iterator until the current file is found
if next(self.dirIterator) == filename:
break
def nextImage(self):
# ensure that the file list has not been cleared due to missing files
if self.fileList:
try:
filename = next(self.dirIterator)
pixmap = QtGui.QPixmap(filename).scaled(self.label.size(),
QtCore.Qt.KeepAspectRatio)
if pixmap.isNull():
# the file is not a valid image, remove it from the list
# and try to load the next one
self.fileList.remove(filename)
self.nextImage()
else:
self.label.setPixmap(pixmap)
except:
# the iterator has finished, restart it
self.dirIterator = iter(self.fileList)
self.nextImage()
else:
# no file list found, load an image
self.loadImage()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
imageLoader = ImageLoader()
imageLoader.show()
sys.exit(app.exec_())
推荐阅读
- c# - C# 脚本在运行下一步之前未完成 SQL 查询
- express - ExpressJS + Axios:无法发送标头授权
- java - 追加到 Kotlin 数据类 ArrayList
- google-cloud-dataflow - Apache Beam 中的 Gcloud 主题转义
- c# - 只有一位用户收到 HttpContext Null 错误
- android - 永久存储实例变量
- excel - =IF(A2-D2,0,IF(B2=D2,0,0))。声明不起作用
- php - 根据html中的DIV ID设置php变量
- laravel - Laravel vue axios 是 ajax 表单需要的 action 方法和 csrf
- c++ - 如何让“工厂函数”返回不可复制的对象?