首页 > 解决方案 > 当按钮单击时在目录中显示下一个图像

问题描述

我正在尝试在 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 和循环迭代器之间的连接,但不知道如何。

标签: python-3.xclickpyqt5itertools

解决方案


首先,你不应该使用全局变量,尤其是敏感的和“通用”的名字,比如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_())

推荐阅读