简体   繁体   English

如何让 askopenfilenames 遍历用户输入?

[英]How to get askopenfilenames to loop over a user input?

I've just started learning Python and I'm trying to achieve this in tkinter :我刚刚开始学习 Python,我正在尝试在tkinter实现这一目标:

  • Get user to select any multiple number of files in any directory locations and store it in another folder让用户在任何目录位置选择任意多个文件并将其存储在另一个文件夹中

I'm not sure if there's any other more efficient ways of doing this but I've tried solving this by:我不确定是否还有其他更有效的方法可以做到这一点,但我尝试通过以下方式解决这个问题:

  • Getting the user to input how many files they are searching for (I set 2 as default)让用户输入他们要搜索的文件数量(我默认设置为 2)
  • loop over the number of files and ask for the user to select the files遍历文件数并要求用户选择文件
  • send all the files to the new location将所有文件发送到新位置

The problem is I can't quite get the storing the files and looping to work well.问题是我无法让存储文件和循环正常工作。 Here's the code:这是代码:

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()

Solution1 (as per your needs - when files can be in different locations)解决方案 1(根据您的需要 - 当文件可以位于不同位置时)

Things to note: I changed filedialog.askopenfilenames() to filedialog.askopenfilename() because if the user is supposed to copy exact number of files overall (defined by user input in self.var ), in that case, allowing the user to select more than one file at a time may result in exceeding the value of self.var because our for loop will always run self.var.get() times , and if user selects two(say) files on each iteration , he will end up copying 2*self.var.get() files in total, and your idea of asking for the exact number of files to copy in the start will not do any good for us.注意事项:我将filedialog.askopenfilenames()更改为filedialog.askopenfilename()因为如果用户应该复制整个文件的确切数量(由用户在self.var输入定义),在这种情况下,允许用户选择一次多个文件可能会导致超过self.var的值,因为我们的for loop将始终运行self.var.get() times ,如果用户在每次iteration选择两个(比如说)文件,他将最终总共复制2*self.var.get()文件,并且您在开始时要求复制文件的确切数量的想法对我们没有任何好处。

Your code was not working because you were setting the file_list variable to a new value list(files_chosen) on every iteration (instead of appending it to the list)您的代码不起作用,因为您在每次iteration都将file_list变量设置为新值list(files_chosen) (而不是appendingappending到列表中)

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 (can select multiple files - all in same directory)解决方案2(可以选择多个文件 - 都在同一目录中)

This is recommended and you will see this approach being used in almost every application.这是推荐的,您会看到这种方法几乎用于每个应用程序。 Here You don't need to ask the user about how many files do they wish to copy.在这里,您无需询问用户他们希望复制多少个文件。 They can select anywhere from a single file to 1000 files (if present & required),but files will be supposed to be in same directory .他们可以选择从单个文件到 1000 个文件(如果存在和需要)的任何位置,但文件应该位于同一directory For files of other directories they can click on select files button again, follow the process.对于其他目录的文件,他们可以再次单击select files按钮,按照流程操作。

Note that I did not remove the label and entry box for entering the number of files, but consider them ignored from the GUI.请注意,我没有删除用于输入文件数量的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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM