【问题标题】:How to get askopenfilenames to loop over a user input?如何让 askopenfilenames 遍历用户输入?
【发布时间】:2020-12-28 13:07:41
【问题描述】:

我刚刚开始学习 Python,我正在尝试在 tkinter 中实现这一目标:

  • 让用户在任何目录位置选择任意多个文件并将其存储在另一个文件夹中

我不确定是否还有其他更有效的方法,但我已尝试通过以下方式解决此问题:

  • 让用户输入他们正在搜索的文件数量(我将 2 设为默认值)
  • 遍历文件数量并要求用户选择文件
  • 将所有文件发送到新位置

问题是我无法让存储文件和循环正常工作。代码如下:

import tkinter as tk
from tkinter import filedialog, ttk
import shutil


class Getfiles():
    def __init__(self):
        #  initialising the screen name, size title and icon
        root = tk.Tk()
        root.geometry('450x100')
        root.resizable(0, 0)
        root.configure(bg='#002060')

        # initialising integer value to pass to select_files method
        self.var = tk.IntVar()
        self.var.set('2')

        # Initialising the frame to insert our widget
        frame_three = tk.Frame(root, bg='#002060')
        frame_three.pack(side='top', fill='both')

        # setting label to tell user to input no. of files
        num_label = ttk.Label(frame_three, text='No. of files: ', background='#002060', foreground='white')
        num_label.pack(side='left', padx=(40, 10), pady=(20, 20))

        # setting number of files user wants to fetch
        files_num = ttk.Entry(frame_three, width=3, textvariable=self.var)
        files_num.pack(side='left', padx=(10, 40), pady=20)

        # get user to select the files listed
        select_button = ttk.Button(frame_three, text='Select files', width=30, command=self.select_files)
        select_button.pack(side='left', padx=(50, 10))

        root.mainloop()


    def select_files(self):
        file_list = []
        for i in range(self.var.get()):
            file_chosen = filedialog.askopenfilenames(title='Choose a file')
            file_list = list(file_chosen)
            list += file_list
        self.copy(file_list)

    def copy(self, file_list):
        destination = filedialog.askdirectory()
        for file in file_list:
            shutil.copy(file, destination)


if __name__ == '__main__':
    Getfiles()

【问题讨论】:

  • 所有文件(最初)是否都存储在同一个目录中(在将它们移动到新目录之前)?
  • 不一定
  • 好吧,当他们在同一个目录中时,我有一个答案。现在写答案,并将添加有关如何在不在正常目录中的情况下实施它的信息。

标签: python python-3.x tkinter filedialog


【解决方案1】:

解决方案1(根据您的需要 - 当文件可以位于不同位置时)

注意事项:我将filedialog.askopenfilenames() 更改为filedialog.askopenfilename(),因为如果用户应该复制确切数量的文件(由self.var 中的用户输入定义),在这种情况下,允许用户选择更多一次超过一个文件可能导致超过self.var 的值,因为我们的for loop 将始终运行self.var.get() times,如果用户在每个iteration 上选择两个(比如说)文件,他最终将复制@987654328 @ 文件总数,而您在开始时询问要复制的确切文件数量的想法对我们没有任何好处。

您的代码无法正常工作,因为您在每个 iteration 上将 file_list 变量设置为新值 list(files_chosen)(而不是 appending 将其设置为列表)

import tkinter as tk
from tkinter import filedialog, ttk
import shutil


class Getfiles():
    def __init__(self):
        #  initialising the screen name, size title and icon
        root = tk.Tk()
        root.geometry('450x100')
        root.resizable(0, 0)
        root.configure(bg='#002060')

        # initialising integer value to pass to select_files method
        self.var = tk.IntVar()
        self.var.set('2')

        # Initialising the frame to insert our widget
        frame_three = tk.Frame(root, bg='#002060')
        frame_three.pack(side='top', fill='both')

        # setting label to tell user to input no. of files
        num_label = ttk.Label(frame_three, text='No. of files: ', background='#002060', foreground='white')
        num_label.pack(side='left', padx=(40, 10), pady=(20, 20))

        # setting number of files user wants to fetch
        files_num = ttk.Entry(frame_three, width=3, textvariable=self.var)
        files_num.pack(side='left', padx=(10, 40), pady=20)

        # get user to select the files listed
        select_button = ttk.Button(frame_three, text='Select files', width=30, command=self.select_files)
        select_button.pack(side='left', padx=(50, 10))

        root.mainloop()


    def select_files(self):
        files_list = []
        
        for x in range(self.var.get()):
            files_chosen = filedialog.askopenfilename(title='Choose a file')
            files_list += list(files_chosen)

        self.copy(files_list)

    def copy(self, file_list):
        destination = filedialog.askdirectory()
        for file in file_list:
            shutil.copy(file, destination)


if __name__ == '__main__':
    Getfiles()

solution2(可以选择多个文件 - 都在同一个目录中)

这是推荐的,您会看到几乎所有应用程序都在使用这种方法。在这里,您无需询问用户他们希望复制多少个文件。他们可以选择从单个文件到 1000 个文件(如果存在和需要)的任何地方,但文件应该在相同的 directory 中。其他目录的文件可以再次点击select files按钮,按照流程操作。

请注意,我并没有删除用于输入文件数量的 labelentry 框,而是将它们从 GUI 中忽略。

import tkinter as tk
from tkinter import filedialog, ttk
import shutil


class Getfiles():
    def __init__(self):
        #  initialising the screen name, size title and icon
        root = tk.Tk()
        root.geometry('450x100')
        root.resizable(0, 0)
        root.configure(bg='#002060')

        # initialising integer value to pass to select_files method
        self.var = tk.IntVar()
        self.var.set('2')

        # Initialising the frame to insert our widget
        frame_three = tk.Frame(root, bg='#002060')
        frame_three.pack(side='top', fill='both')

        # setting label to tell user to input no. of files
        num_label = ttk.Label(frame_three, text='No. of files: ', background='#002060', foreground='white')
        num_label.pack(side='left', padx=(40, 10), pady=(20, 20))

        # setting number of files user wants to fetch
        files_num = ttk.Entry(frame_three, width=3, textvariable=self.var)
        files_num.pack(side='left', padx=(10, 40), pady=20)

        # get user to select the files listed
        select_button = ttk.Button(frame_three, text='Select files', width=30, command=self.select_files)
        select_button.pack(side='left', padx=(50, 10))

        root.mainloop()


    def select_files(self):
        files_list = []

        files_chosen = filedialog.askopenfilenames(title='Choose a file')

        self.copy(list(files_chosen))

    def copy(self, file_list):
        destination = filedialog.askdirectory()
        for file in file_list:
            shutil.copy(file, destination)


if __name__ == '__main__':
    Getfiles()

【讨论】:

  • @DaveWhite 没问题 :) 如果它解决了您的问题(或回答了您的问题),请考虑支持或接受答案。
猜你喜欢
  • 1970-01-01
  • 2018-01-29
  • 2018-05-23
  • 2016-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多