如何使用 tkinter OpenFileDialog 打开多个文件?

问题描述 投票:0回答:1

我正在努力完成我的计划。我正在使用 tkinter OpenFileDialog (AskOpenFile) 打开 .txt 文件并绘制它。我需要一次打开多个文件并使用这些文件。我的函数 AskOpenFile 运行良好,但我想使用 AskOpenFiles 函数,这样我就可以同时处理多个文件。从多个 .txt 文件中创建一个图。有人可以帮我吗?我收到以下消息: Tkinter 回调中出现异常 回溯(最近一次调用最后一次):

File "C:\Users\m.salik\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1962, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\m.salik\PycharmProjects\pythonProject\Polycontact\GUI_main.py", line 95, in select_file
    Analysis_frame.analysis(self)
  File "C:\Users\m.salik\PycharmProjects\pythonProject\Polycontact\GUI_main.py", line 19, in analysis
    data = pd.read_csv(data_raw, sep=";", skiprows=[0], low_memory=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\m.salik\PycharmProjects\pythonProject\.venv\Lib\site-packages\pandas\io\parsers\readers.py", line 948, in read_csv
    return _read(filepath_or_buffer, kwds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\m.salik\PycharmProjects\pythonProject\.venv\Lib\site-packages\pandas\io\parsers\readers.py", line 611, in _read
    parser = TextFileReader(filepath_or_buffer, **kwds)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\m.salik\PycharmProjects\pythonProject\.venv\Lib\site-packages\pandas\io\parsers\readers.py", line 1448, in __init__
    self._engine = self._make_engine(f, self.engine)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\m.salik\PycharmProjects\pythonProject\.venv\Lib\site-packages\pandas\io\parsers\readers.py", line 1720, in _make_engine
    raise ValueError(msg)
ValueError: Invalid file path or buffer object type: <class 'list'>

我的代码:

````   import tkinter as tk
   from tkinter import *
   from tkinter import messagebox
   from tkinter import filedialog as fd
   import pandas as pd
   import matplotlib.pyplot as plt

class Analysis_frame(tk.LabelFrame):
    def __init__(self, container):
        super().__init__(container)
        self.configure(text="Analysis", relief="ridge", font=("Verdana", 10), borderwidth=1, border=3)

        self.__create_widgets()

    def analysis(self):
        global Test_Start, Test_End, Duration, Duration_End, Temperature, MinTemp, MaxTemp, Start_Time,  End_Time
        global Current_IN_max, Current_IN_min, MaxValue_I_IN_max, MinValue_I_IN_max
        global data
        data = pd.read_csv(data_raw, sep=";", skiprows=[0], low_memory=False)
        # print(data_raw.columns)
        Test_Start = data.iloc[:, 0].values[0]
        Test_End = data.iloc[:, 0].values[-1]
        Start_Time = data.iloc[:, 1].values[0]
        End_Time = data.iloc[:, 1].values[-1]
        Duration = data.iloc[:, 3]
        Duration_End = data.iloc[:, 3].values[-1]
        Temperature = data.iloc[:, 4]
        MinTemp = Temperature.min()
        MaxTemp = Temperature.max()
        Humidity = data.iloc[:, 5]
        Supply_IN_max = data.iloc[:, 8]
        Supply_IN_min = data.iloc[:, 9]
        Current_IN_max = data.iloc[:, 12]
        Current_IN_min = data.iloc[:, 13]
        Voltage_OUT_max = data.iloc[:, 20]
        pd.set_option("display.max_rows", 20000)

#####   Temperature diagram    #####
    def __create_plot_temp(self):
        fig, ax1 = plt.subplots(facecolor="white", figsize=(17,10), dpi=100)
        ax1.set_title("Temperature diagram", font="Verdana", fontsize=11)
        ax1.set_facecolor("whitesmoke")
        plt.subplots_adjust(left=0.05, right=0.95, top=0.98, bottom=0.15)


        ax1.set_ylim(bottom=0, top=1)
        ax1.set_xlim(0,Duration_End)
        ax2 = ax1.twinx()
        ax2.set_ylim(bottom=MinTemp-10, top=MaxTemp+15)
        ax1.minorticks_on()
        plt.minorticks_on()
        ax1.set_ylabel("Current [A]").set_fontsize(10)
        ax2.set_ylabel("Temperature [°C]").set_fontsize(10)
        ax1.set_xlabel("Test duration [h]").set_fontsize(10)

        sample1, = ax1.plot(Duration, Current_IN_max, label="IGSS1", color="green", marker=".", markersize=2,
                            mouseover=True, linewidth=0.2, visible=True, alpha=0.5)
        sample2, = ax1.plot(Duration, Current_IN_min, label="IGSS2", color="orange", marker=".", markersize=2,
                            mouseover=True, linewidth=0.2, visible=True, alpha=0.5)
        temp, = ax2.plot(Duration, Temperature, label="Temperature", color="red", linewidth=0.8, alpha=0.7)


        plt.figtext(0.05,0.10,f"Test start: {Test_Start +" "+ Start_Time}", fontfamily="verdana", fontsize=10)
        plt.figtext(0.85,0.10, f"Test end: {Test_End +" "+ End_Time}", fontfamily="verdana", fontsize=10)
        plt.show()

    def __create_widgets(self):
        tk.Button(self, text="Temperature" "\n" "diagram", font=("Verdana", 8), command=self.__create_plot_temp).grid(
            column=0, row=0, sticky=tk.S)


        for widget in self.winfo_children():        # spacings for all widgets within the frame
            widget.grid(padx=5, pady=5)

class Button_frame(tk.LabelFrame):                  # create frame
    def __init__(self, container):
        super().__init__(container)
        self.configure(text="Files", font=("Verdana", 10), relief="ridge", borderwidth=1, border=3)

        self.__create_widgets()

    def select_file(self):                          # function for opening the csv files, command for open_file button
        global data_raw
        filetypes = (
            ("textfiles", ".txt"),
        )
        file = fd.askopenfiles(
            filetypes=filetypes,
            mode="r+",
            title="Open file",
            initialdir="/",
        )
        if file is not None:
            data_raw = file
            Analysis_frame.analysis(self)
            messagebox.showinfo("Data", "Data loaded succesfull!")
        else:
            messagebox.showinfo("Data", "No data loaded!")

    def __create_widgets(self):                         # create buttons within the frame
        open_file = tk.Button(self, text="Open csv file", font=("Verdana", 8), command=self.select_file)
        open_file.grid(column=0, row=0, sticky=N)

        exit = tk.Button(self, text="Close", font=("Verdana", 8), command=quit)
        exit.grid(column=1, row=0, sticky=N)

        for widget in self.winfo_children():        # spacings for all widgets within the frame
            widget.grid(padx=5, pady=5)

class Main_window(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Analysis")
        self.geometry("600x500")
        #self.attributes("-toolwindow", True)

        self.__create_widgets()

    def __create_widgets(self):

        analysis = Analysis_frame(self)
        analysis.grid(column=0, row=2, sticky=NW)

        buttons = Button_frame(self)
        buttons.grid(column=0, row=1, sticky=NW)

        for widget in self.winfo_children():        # spacings for all widgets within the main window
            widget.grid(padx=5, pady=5)

if __name__ == "__main__":
    app = Main_window()
    app.mainloop()```
python-3.x tkinter openfiledialog
1个回答
0
投票

问题在这里:

file = fd.askopenfiles(
            filetypes=filetypes,
            mode="r+",
            title="Open file",
            initialdir="/",
        )

askopenfiles
返回
list
文件(即使您只选择一个文件),所以这就是您收到错误的原因

ValueError: Invalid file path or buffer object type: <class 'list'>

如果要依次打开并处理选定的文件,则需要像这样迭代

askopenfiles
返回的列表

def select_file(self):
    global data_raw
    filetypes = ("textfiles", ".txt")
    files = fd.askopenfiles(  # changed this to 'files' since it's a list of multiple files
        filetypes=filetypes,
        mode="r+",
        title="Open file",
        initialdir="/",
    )
    for file in files:  # iterate over the list of files
         if file is not None:
            data_raw = file
            Analysis_frame.analysis(self)
            messagebox.showinfo("Data", "Data loaded succesfull!")
        else:
            messagebox.showinfo("Data", "No data loaded!")
© www.soinside.com 2019 - 2024. All rights reserved.