我正在尝试创建一个“从 csv 文件读取”类。这个类应该读取一个 csv 文件并将结果作为列表返回。到目前为止 - 即使对于像我这样的新手来说也很简单。
但是-我需要一些更复杂的东西:
1) 如果没有给出文件名(作为类的参数)——弹出一个文件选择对话框来选择一个。
2) 可选:使用 CSVGui 类(使用方法 self.out_in_gui)在 GUI 中显示文件内容。
由于 ReadCSV 不是基于 GUI 的类,GUI 仅在需要启动 askopenfilename 时初始化。使用 widtdraw() 是为了不显示额外的空白 GUI。
问题是:当我尝试读取一个文件时,没有指定一个文件,弹出一个文件选择对话框,加上调用方法self.out_in_gui来执行CSVGui 类 - 文件内容不显示在 GUI 中(条目留空)。
TRIES:当我指定要加载的文件作为参数时,一切运行正常。我的猜测 - 它与使用 ReadFile 中的 GUI 加载文件选择 GUI 有关。
谢谢 J
import csv
import tkinter as tk
from tkinter import ttk
from tkinter.filedialog import askopenfilename
class ReadFile:
"""This class reads CSV w/out header line, and returen it as a list"""
def __init__(self, fname='', path='', **kwargs):
if fname == '' and path == '':
tk.Tk().withdraw()
self.filename = askopenfilename(title='Select CSV file', filetypes=[('CommaSeperatedFile', '*.csv')])
else:
if path != '':
self.filename = path + '/' + fname
else:
self.filename = fname
self.file_content = []
self.read_file(kwargs)
self.out_in_gui()
def read_file(self, kwargs):
with open(self.filename, newline='', **kwargs) as csvfile:
file_obj = csv.reader(csvfile)
for i in file_obj:
self.file_content.append(i)
print("file %s was read successfully, containing %d lines" % (self.filename, len(self.file_content)))
def out_in_gui(self):
print("send data to CSVGui")
CSVGui(self, data=self.file_content)
def file_contents(self):
return self.file_content
class CSVGui(ttk.Frame):
def __init__(self, master=None, data=[]):
ttk.Frame.__init__(self, master)
self.master = master
# csvroot = tk.Tk()
fname = 'No file loaded'
# if data is not None and master is not None:
# fname = self.master.filename
# csvroot.title("CSVGui - " + fname)
self.frame = ttk.LabelFrame(self, text='Data set', padding=10)
self.frame.grid(row=0, column=0, padx=5, pady=5)
self.widgets_frame = ttk.Frame(self)
self.widgets_frame.grid(row=1, column=0)
self.m, self.row_vars = [], []
self.exec_gui(data)
print(data)
# self.read_from_gui()
# csvroot.mainloop()
def exec_gui(self, data):
# populted and create GUI with data
for r in range(len(data)):
self.m = []
self.ent = ''
for col in range(len(max(data))):
self.m.append(tk.StringVar())
self.ent = ttk.Entry(self.frame, textvariable=self.m[-1], state=tk.NORMAL)
self.ent.grid(row=r, column=col)
try:
self.m[-1].set(data[r][col])
print("IN")
except IndexError:
self.m[-1].set('')
print("OUT")
# create structured vector of var for use in save mode
self.row_vars.append(self.m)
self.create_widgets()
print("CSVGui - Created")
def create_widgets(self):
self.save_button = ttk.Button(self.widgets_frame, text='Save', command=self.save2file)
self.save_button.grid(row=0, column=0)
self.exit_button = ttk.Button(self.widgets_frame, text='Exit') # , command=print('Exit'))
self.exit_button.grid(row=0, column=1)
tk.Spinbox(self.widgets_frame, width=5, from_=0, to=20).grid()
def read_from_gui(self):
data_list = []
for r, rows in enumerate(self.row_vars):
c_data = []
for c, cols in enumerate(rows):
if cols.get() != '':
c_data.append(cols.get())
data_list.append(c_data)
return data_list
def save2file(self):
WriteFile('w', self.master.filename, data=self.read_from_gui())
请您参考如下方法:
我试过你的代码,但它对我不起作用,因为问题是 master
在 ReadFile 中运行 CSVGui(self, ...) 并且 self 表示 ReadFile。在 CSVGui 中,您将此 ReadFile 分配给 master 并在 ttk.Frame.__init__(self, master) 中使用 -但 master 必须是任何 tkinter 的 小部件,而不是 ReadFile。
我修改了两个地方
首先:在 ReadFile 中,我创建了 Tk() 窗口,在 askopenfilename 之后,我销毁了它。这样,如果我运行 ReadFile() 或 ReadFile(filename.csv) 我总是会在没有 master 的情况下运行 CSVGui在计算机内存中。
if fname == '' and path == '':
master = tk.Tk()
master.withdraw()
self.filename = askopenfilename(title='Select CSV file', filetypes=[('CommaSeperatedFile', '*.csv')])
master.destroy()
第二:CSVGui 不需要 master 作为第二个参数,因为我在 CSVGui 中创建了它
class CSVGui(ttk.Frame):
def __init__(self, data=[]):
master = tk.Tk()
ttk.Frame.__init__(self, master)
它还需要 self.pack() 把 class CSVGui(ttk.Frame) 放在这个 master 里面,和 master.mainloop() 使其保持打开状态。
import csv
import tkinter as tk
from tkinter import ttk
from tkinter.filedialog import askopenfilename
class ReadFile:
"""This class reads CSV w/out header line, and returen it as a list"""
def __init__(self, fname='', path='', **kwargs):
if fname == '' and path == '': # <--- changes
master = tk.Tk()
master.withdraw()
self.filename = askopenfilename(title='Select CSV file', filetypes=[('CommaSeperatedFile', '*.csv')])
master.destroy()
else:
if path != '':
self.filename = path + '/' + fname
else:
self.filename = fname
self.file_content = []
self.read_file(kwargs)
self.out_in_gui()
def read_file(self, kwargs):
with open(self.filename, newline='', **kwargs) as csvfile:
file_obj = csv.reader(csvfile)
for i in file_obj:
self.file_content.append(i)
print("file %s was read successfully, containing %d lines" % (self.filename, len(self.file_content)))
def out_in_gui(self):
print("send data to CSVGui")
CSVGui(self.filename, data=self.file_content) # <--- changes
def file_contents(self):
return self.file_content
class CSVGui(ttk.Frame):
def __init__(self, filename, data=[]): # <--- changes
self.filename = filename # <--- changes
master = tk.Tk() # <--- changes
ttk.Frame.__init__(self, master)
self.grid() # <--- changes (updated. was `pack` before)
# csvroot = tk.Tk()
fname = 'No file loaded'
# if data is not None and master is not None:
# fname = self.master.filename
# csvroot.title("CSVGui - " + fname)
self.frame = ttk.LabelFrame(self, text='Data set', padding=10)
self.frame.grid(row=0, column=0, padx=5, pady=5)
self.widgets_frame = ttk.Frame(self)
self.widgets_frame.grid(row=1, column=0)
self.m, self.row_vars = [], []
self.exec_gui(data)
print(data)
# self.read_from_gui()
# csvroot.mainloop()
master.mainloop() # <--- changes
def exec_gui(self, data):
# populted and create GUI with data
for r in range(len(data)):
self.m = []
self.ent = ''
for col in range(len(max(data))):
self.m.append(tk.StringVar())
self.ent = ttk.Entry(self.frame, textvariable=self.m[-1], state=tk.NORMAL)
self.ent.grid(row=r, column=col)
try:
self.m[-1].set(data[r][col])
print("IN")
except IndexError:
self.m[-1].set('')
print("OUT")
# create structured vector of var for use in save mode
self.row_vars.append(self.m)
self.create_widgets()
print("CSVGui - Created")
def create_widgets(self):
self.save_button = ttk.Button(self.widgets_frame, text='Save', command=self.save2file)
self.save_button.grid(row=0, column=0)
self.exit_button = ttk.Button(self.widgets_frame, text='Exit') # , command=print('Exit'))
self.exit_button.grid(row=0, column=1)
tk.Spinbox(self.widgets_frame, width=5, from_=0, to=20).grid()
def read_from_gui(self):
data_list = []
for r, rows in enumerate(self.row_vars):
c_data = []
for c, cols in enumerate(rows):
if cols.get() != '':
c_data.append(cols.get())
data_list.append(c_data)
return data_list
def save2file(self):
WriteFile('w', self.filename, data=self.read_from_gui()) # <--- changed
ReadFile()
编辑:我将 filename 添加到 CSVGui(self.filename, data=self.file_content)
