【问题标题】:Get file details (complete file path) from the filename (only basename) existing as a text in tkinter Text widget从 tkinter Text 小部件中作为文本存在的文件名(仅基名)获取文件详细信息(完整文件路径)
【发布时间】:2020-12-24 08:47:54
【问题描述】:

在以下代码的帮助下,我在 tkinter Text 小部件中插入文件名(文件基名),然后在按下“获取数据”按钮后尝试打印完整的文件路径。

import tkinter as tk
from tkinter.filedialog import askopenfilename
import os

root=tk.Tk()    

ent=tk.Text(root)
ent.grid(row=1,column=0)

def addfile():
    filename =askopenfilename(filetypes=(("Tiff files","*.tif"),("All files","*.*")))
    ent.insert(tk.INSERT, '"' + os.path.basename(filename) + '"') 
    ent.insert(tk.INSERT, "\n")

def getfile():
    print(ent.get("1.0", tk.END))

b=tk.Button(root,text="Select File",command=addfile)
b.grid(row=0,column=0)

b1 = tk.Button(root,text="Get Data",command=getfile)
b1.grid(row=2,column=0)

root.mainloop()

运行上述代码后,仅打印文件名(没有文件路径)。

现在基本上我想要的是,在按下“获取数据”按钮后(读取文本小部件的内容),然后应该打印文件的完整路径。

附加信息:-

我知道如果文件名不同,那么我可以使用字典(键,值)对来链接每个文件的基本名称及其绝对路径。但是当不同的文件存在于不同的文件夹位置但具有相同的名称被添加到文本小部件时,就会出现问题。

【问题讨论】:

  • 我建议用你所期望的和你得到的来编辑 Q,让它更清楚

标签: python tkinter


【解决方案1】:

正如 Cool Cloud 评论的那样,很难给出您需要的确切答案,因为您还没有告诉我们正在发生什么以及您期望/会发生什么。

我的阅读方式是你想要的:

  1. 您从askopenfilename() 收到的要插入Text 小部件的整个文件名。
  2. 您希望在单击Button b1 时打印整个文件名,但保留Text 小部件。

1.我会把def addfile():改成

def addfile():
    filename = askopenfilename()
    ent.insert(tk.INSERT, '"' + filename + '"\n')

这样做是插入完整的文件路径而不仅仅是基本名称,即它会插入"D:/example/help.tif" 而不仅仅是help.tif

2.我会使用下面的代码

root = tk.Tk()

def addfile():
    filename = askopenfilename()
    list_of_filenames.append(filename)
    ent.insert(tk.INSERT, '"' + os.path.basename(filename) + '"\n') 

def getfile():
    for i in range(len(list_of_filenames)):
        print(list_of_filesnames[i])
                   

list_of_filenames = []

ent = tk.Text(root)
ent.grid(row=1, column=0)

b=tk.Button(root,text="Select File",command=addfile)
b.grid(row=0,column=0)

b1 = tk.Button(root,text="Get Data",command=getfile)
b1.grid(row=2,column=0)

root.mainloop()

我所做的是创建一个名为list_of_filenames 的全局列表变量,并在def addfile(): 中添加了list_of_filenames.append(filename) 行,这将获取您选择的文件和路径,并将其添加到列表变量中。因此,为您提供了一个包含您选择的每个文件的列表,并且您构建的任何函数都可以访问它,因为它是全局的。

最后的更改是def getfile():,这可以完全按照您的意愿完成,我已经编写了它以将每个文件单独打印在单独的行上,没有方括号或引号。

使用与第 1 部分相同的示例,如果我选择路径为 D:/example/help.tif 的文件,Text 小部件将显示为“help.tif”,并且当单击 b1 时,D:/example/help.tif 将打印到安慰。

【讨论】:

  • 我怀疑如果我在文本小部件中添加 2 个文件(存在于不同的文件夹中,例如 D:/example1/help.tif、D:/example2/help.tif),然后在文本小部件中将出现 2 个“help.tif”条目。现在,如果我从文本小部件中删除任何一个 help.tif 条目,然后按“获取数据”按钮,它就是一个文本小部件,那么它将打印 help.tif。那我怎么知道这个help.tif对应的是哪个文件夹“example1”或“example2”。
  • 当您有 2 个 "help.tif" 时,Text 小部件是否必须在您的示例中读取两次 "help.tif",或者如果基本名称重复,您是否可以有 "help.tif""example2/help.tif"
  • 在当前场景中,我向文本小部件添加了 2 个 help.tif 文件(对应于两个不同的文件夹,即 example1 和 example2)。现在这 2 个 help.tif 文件对应于两个不同的路径,即“D:/example1/help.tif”、“D:/example2/help.tif”。现在假设如果我手动删除一个 help.tif 文件(其他 help.tif 文件仍然存在于文本小部件中),然后按“获取数据”按钮,那么最后我希望此函数返回现有 help.tif 文件的绝对路径打印出来。
  • 我已经尽我所能用你提供的信息,我会用我的代码添加另一个答案。
【解决方案2】:

我将拆分我的代码来尝试解释我所做的事情。

前 4 个功能是执行 addfile(): 以及您要求的其他事情。

  1. 第一个函数split_filename(path): 按照函数名称的说明进行操作。它将采用输入的路径并创建路径各个部分的列表。 (即,如果您有 D:/folder/example/help/test.tif,它将返回 ['D:/', 'folder', 'example', 'help', 'test.tif'],稍后您会发现,当您有 2 个相同的基本名称时,这很有用。
def split_filename(path):
    allParts = []
    while 1:
        parts = os.path.split(path)
        if parts[0] == path:
            allParts.insert(0, parts[0])
            break
        elif parts[1] == path:
            allParts.insert(0, parts[1])
            break
        else:
            path = parts[0]
            allParts.insert(0, parts[1])
    return allParts
  1. check_if_fileBasename_in_current_content(current_content, selected_file_basename): 函数名称再次告诉您它的作用。这会检查新选择的文件基名是否已经在 Text 小部件中。
def check_if_fileBasename_in_current_content(current_content, selected_file_basename):
    for line in current_content:
        if line == '':
            pass
        elif line == selected_file_basename:
            return True
  1. 如果Text 小部件中已存在新选择的文件基名,则调用第三个if_true_split_path_for_basename(selected_file_path, selected_file_basename):。该函数采用新选择的文件和已保存的 1 的路径。如果您有 2 个文件:D:/example1/help.tif(新选择)和 D:/example2/help.tif(先前添加),新选择的基本名称将变为 example2/help.tif 而不仅仅是 help.tif。通过这样做,可以区分两个文件之间的差异。在函数结束时,创建的基本名称认为函数被插入ent 并添加到字典dict_of_filenames(这在单击b1 时打印路径时很有用。)
def if_true_split_path_for_baseline(selected_file_path, selected_file_basename):
    basename_for_text_widget = []
    if selected_file_path in dict_of_filenames:
        pass
    else:
        for path, basename in dict_of_filenames.items():
            if basename == selected_file_basename:
                duplicate_path_split = split_filename(path)
                selected_file_path_split = split_filename(selected_file_path)
                for i in range(len(selected_file_path_split)):
                    duplicate_slice = duplicate_path_split[-(i + 1)]
                    selected_slice = selected_file_path_split[-(i + 1)]
                    if duplicate_slice == selected_slice:
                        basename_for_text_widget.insert(0, selected_slice)
                    else:
                        basename_for_text_widget.insert(0, selected_slice)
                        break

        ent.insert(tk.INSERT, str('/'.join(basename_for_text_widget) + '\n'))
        dict_of_filenames.update({selected_file_path: '/'.join(basename_for_text_widget)})
  1. addFile()链接以上所有功能,它:索要文件;获取基本名称;获取所有当前文本在Text 小部件中;检查基本名称是否已经存在,如果存在则调用函数 3(上文),最后如果它是新的基本名称,则将基本名称插入ent 并将路径和基本名称添加到字典中。
def addFile():
    selected_file_path = askopenfilename(filetypes=(("Tiff files", "*.tif"), ("All files", "*.*")))
    selected_file_basename = os.path.basename(selected_file_path)
    current_content = ent.get("1.0", tk.END).splitlines()

    check1 = check_if_fileBasename_in_current_content(current_content, selected_file_basename)
    basename_for_text_widget = []
    if check1:
        if_true_split_path_for_baseline(selected_file_path, selected_file_basename)

    else:
        basename_for_text_widget.append(selected_file_basename)
        dict_of_filenames.update({selected_file_path: ''.join(basename_for_text_widget)})
        ent.insert(tk.INSERT, str(' '.join(basename_for_text_widget) + '\n'))

接下来是getFile():ent的内容,然后取basename并打印对应的路径。

def getFile():
    current_content = ent.get(1.0, tk.END).splitlines()
    for path, basename in dict_of_filenames.items():
        if basename in current_content:
            print(path)

您需要做的最后一个更改是创建全局字典 通过在def getFile(): 函数下方添加dict_of_filename = {} 插入,没有像TextButton 变量那样的缩进

其他一切都保持原样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    相关资源
    最近更新 更多