【问题标题】:Listbox update global list contents列表框更新全局列表内容
【发布时间】:2017-01-24 21:00:59
【问题描述】:

我正在制作一个 GUI,用户可以在其中导入 CSV 文件,并且可以单击对这些文件执行功能的各种按钮,例如绘制 CSV、查看 CSV 的迷你表格等。每当导入文件时,它都会被附加到名为 file_list 的全局列表中,我的函数通过此全局列表对文件进行操作。

我有一个Listbox 我正在显示在大型机中,我想在其中显示用户已导入的文件列表。我正在使用 for 循环来显示 Listbox 中每个文件的名称,但它似乎不起作用。关于如何显示这些文件名的任何提示?这是我主要的FrameListbox 的代码:

from matplotlib import pyplot
from csv import reader
from dateutil import parser
import tkinter as tk
from tkinter import ttk  
from tkinter.filedialog import askopenfilename
import pandas as pd
from tkinter import Text, Scrollbar, Toplevel

file_list = []

# i'm just including openfile here, which is essentially an import button. 

def openfile():
    name= askopenfilename()
    # file_list is appended with name everytime openfile is clicked
    rev = (name[::-1])
    i = rev.index('/')
    name = ((rev[:i])[::-1])
    file_list.append(name)
    main_dataview.insert(0, name)
    with open(name, 'r') as f:
        data = list(reader(f))
    popup = tk.Tk()
    popup.wm_title("!")
    # popups a message notifying what was imported
    label = ttk.Label(popup, text=" %s was just imported" % (name), font=NORM_FONT)
    label.pack(side="top", fill="x", pady=10)
    B1 = ttk.Button(popup, text="Okay", command = popup.destroy)
    B1.pack()
    center(popup)
    popup.mainloop()

class CODAQ(tk.Tk):

    def __init__(self, *args, **kwargs):  
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "CODAQ")

        # main frame
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        # creates the menubar at the top of the window  
        menubar = tk.Menu(container)

        # import menu for importing csv files, initializes openfile() functions
        filemenu = tk.Menu(menubar, tearoff=0)
        filemenu.add_command(label="Import a CSV File", command = openfile)
        filemenu.add_command(label="Remove", command = remove)
        menubar.add_cascade(label= "File", menu=filemenu)

        # plot menu for creating graphs and figures    
        Plot = tk.Menu(menubar, tearoff =0 )
        Plot.add_command(label="Plot Most Recent CSV", command= popupgraph)
        Plot.add_command(label="Plot an Imported CSV", command = dataselection_graph)
        menubar.add_cascade(label="Plot", menu=Plot)

        # viewdata menu for viewing data in a table
        ViewData = tk.Menu(menubar, tearoff = 0)
        ViewData.add_command(label="View most recent CSV" , command = viewcsv)
        ViewData.add_command(label="View an Imported CSV",command = dataselection_viewcsv)
        ViewData.add_command(label="View most recent CSV Variables",command = variable_extractor)
        ViewData.add_command(label="View an Imported CSV's Variables", command = variable_extractor_sel)
        menubar.add_cascade(label = "View Data", menu = ViewData)

        tk.Tk.config(self, menu=menubar)

        self.frames = {}
        # cycles through screens 
        for F in (WelcomeScreen, MainPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(WelcomeScreen)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

    # WelcomeScreen Object
class WelcomeScreen(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        label1 = ttk.Label(self, text="Welcome to CODAQ", font=LARGE_FONT)
        label2 = ttk.Label(self, text="Begin by importing your Data", font=MEDIUM_FONT)
        label1.pack(pady=0,padx=5)
        label2.pack(pady=15,padx=10)

        button = ttk.Button(self, text="Enter CODAQ",
                        command=lambda: controller.show_frame(MainPage))
        button.pack()


    # mainpage object
class MainPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = ttk.Label(self, text="My Data", font=LARGE_FONT)
        label.grid(row= 0, column = 0, pady = (10,15), padx = (90,0))

        main_dataview = tk.Listbox(self, font=NORM_FONT)
        main_dataview.config(width = 44, borderwidth = 7)

        main_dataview.grid(row=1, column=0, columnspan = 2)

        # scroll bar functionality     
        scroll_y = Scrollbar(self, orient="vertical", command=main_dataview.yview)
        scroll_y.grid(row=1, column=2, sticky="nsew")
        # bind txt to scrollbar
        main_dataview.configure(yscrollcommand=scroll_y.set)


app = CODAQ()
# size of screen 
app.minsize(width=1000, height = 500)
app.mainloop()

【问题讨论】:

  • 可能这个forfile_list 为空时在开始时执行。 file_list 更改内容时不会自动执行。当您向file_list 添加新元素时,您必须手动更新Listbox
  • @furas 我将如何手动更新它?我尝试使用 updateidletask,但我不确定它是如何工作的
  • updateidletask 用于重绘小部件,但每次用户导入新文件时,您都必须再次使用main_dataview.insert(0, file)Listbox 添加元素。
  • main_dataview 属于Mainpage 类,当我将main_dataview.insert(0,file) 添加到我的导入函数时,它说main_dataview 未定义
  • 你会显示完整的代码来理解问题。您是否将文件名添加到file_list之前您启动程序或期间运行程序?如果 before 那么您的代码应该可以工作,如果 during 那么您必须手动将此名称添加到 main_dataview - 但您可能必须使用 self.main_dataview 并执行其他操作这 - 所以它可能更复杂,没有完整的代码我们无法解释它。

标签: python csv tkinter listbox frame


【解决方案1】:

我使用self.main_dataview 从其他函数/类访问Listbox

我将openfile() 放在class CODAQ 中以访问self.framesself.frames[Mainpage].main_dataview - 所以现在我可以插入导入的文件

self.frames[MainPage].main_dataview.insert(0, name)

顺便说一句:tkinter 应该只有一个Tk() 窗口和一个mainloop() - 所以使用Toplevel 创建弹出窗口并删除第二个mainloop()。或使用现有的消息窗口,如

tkinter.messagebox.showinfo('!', " %s was just imported" % (name)) 

要获取没有完整路径的文件名,您可以使用

name = os.path.basename(name)

工作代码:

from matplotlib import pyplot
from csv import reader
from dateutil import parser
import pandas as pd

import tkinter as tk
from tkinter import ttk
from tkinter.filedialog import askopenfilename
from tkinter import Text, Scrollbar, Toplevel
from tkinter.messagebox import showinfo

import os.path

MEDIUM_FONT = (20, )
LARGE_FONT  = (20, )
NORM_FONT   = (20, )

# i'm just including openfile here, which is essentially an import button.

class CODAQ(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "CODAQ")

        # size of screen
        self.minsize(width=1000, height = 500)

        self.file_list = [] # <--

        # main frame
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        # creates the menubar at the top of the window
        menubar = tk.Menu(container)

        # import menu for importing csv files, initializes openfile() functions
        filemenu = tk.Menu(menubar, tearoff=0)
        filemenu.add_command(label="Import a CSV File", command=self.openfile) # <--
        #filemenu.add_command(label="Remove", command = remove)
        menubar.add_cascade(label= "File", menu=filemenu)

        # plot menu for creating graphs and figures
        Plot = tk.Menu(menubar, tearoff =0 )
        #Plot.add_command(label="Plot Most Recent CSV", command= popupgraph)
        #Plot.add_command(label="Plot an Imported CSV", command = dataselection_graph)
        menubar.add_cascade(label="Plot", menu=Plot)

        # viewdata menu for viewing data in a table
        ViewData = tk.Menu(menubar, tearoff = 0)
        #ViewData.add_command(label="View most recent CSV" , command = viewcsv)
        #ViewData.add_command(label="View an Imported CSV",command = dataselection_viewcsv)
        #ViewData.add_command(label="View most recent CSV Variables",command = variable_extractor)
        #ViewData.add_command(label="View an Imported CSV's Variables", command = variable_extractor_sel)
        menubar.add_cascade(label = "View Data", menu = ViewData)

        tk.Tk.config(self, menu=menubar)

        self.frames = {}
        # cycles through screens
        for F in (WelcomeScreen, MainPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(WelcomeScreen)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()


    def openfile(self):
        name = askopenfilename()

        # file_list is appended with name everytime openfile is clicked
        #rev = (name[::-1])
        #i = rev.index('/')
        #name = ((rev[:i])[::-1])

        name = os.path.basename(name) # <---

        self.file_list.append(name)

        self.frames[MainPage].main_dataview.insert(0, name)  # <--

        with open(name, 'r') as f:
            data = list(reader(f))

        showinfo('!', " %s was just imported" % (name))

        #popup = tk.Toplevel() # <--
        #popup.wm_title("!")
        # popups a message notifying what was imported
        #label = ttk.Label(popup, text=" %s was just imported" % (name), font=NORM_FONT)
        #label.pack(side="top", fill="x", pady=10)
        #B1 = ttk.Button(popup, text="Okay", command=popup.destroy)
        #B1.pack()
        #center(popup)

# --- WelcomeScreen Object ---

class WelcomeScreen(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        label1 = ttk.Label(self, text="Welcome to CODAQ", font=LARGE_FONT)
        label2 = ttk.Label(self, text="Begin by importing your Data", font=MEDIUM_FONT)
        label1.pack(pady=0,padx=5)
        label2.pack(pady=15,padx=10)

        button = ttk.Button(self, text="Enter CODAQ",
                        command=lambda: controller.show_frame(MainPage))
        button.pack()

# --- mainpage object ---

class MainPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = ttk.Label(self, text="My Data", font=LARGE_FONT)
        label.grid(row= 0, column = 0, pady = (10,15), padx = (90,0))

        self.main_dataview = tk.Listbox(self, font=NORM_FONT)
        self.main_dataview.config(width = 44, borderwidth = 7)

        self.main_dataview.grid(row=1, column=0, columnspan = 2)

        # scroll bar functionality
        scroll_y = Scrollbar(self, orient="vertical", command=self.main_dataview.yview)
        scroll_y.grid(row=1, column=2, sticky="nsew")
        # bind txt to scrollbar
        self.main_dataview.configure(yscrollcommand=scroll_y.set)

# --- main ---

app = CODAQ()
app.mainloop()

【讨论】:

    【解决方案2】:

    猜测是因为您的问题太多了,但这里有一个可运行的示例,显示了更新 tk.Listbox 的内容。

    try:
        import Tkinter as tk
        import tkFont
        import ttk
    except ImportError:  # Python 3
        import tkinter as tk
        import tkinter.font as tkFont
        import tkinter.ttk as ttk
    
    class MainPage(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self, parent)
            label = ttk.Label(self, text="My Data")
            label.grid(row=0, column=0, pady=(10, 15), padx=(90, 0))
    
            main_dataview = tk.Listbox(self)
            main_dataview.config(width=44, borderwidth=7)
            main_dataview.grid(row=1, column=0, columnspan=2)
    
            for file in file_list:
                main_dataview.insert(tk.END, file)
    
            # make attributes for other methods to use
            self.main_dataview = main_dataview
            self.next_file_number = len(file_list) + 1
    
            # scroll bar functionality
            scroll_y = tk.Scrollbar(self, orient="vertical", command=main_dataview.yview)
            scroll_y.grid(row=1, column=2, sticky="nsew")
            # bind txt to scrollbar
            main_dataview.configure(yscrollcommand=scroll_y.set)
    
            # something to create new listbox entries
            add_button = tk.Button(self, text='Add file', command=self.add_file)
            add_button.grid(row=3, column=0)
    
        def add_file(self):
            """Add a file to the listbox."""
            self.main_dataview.insert(tk.END, 'file_{}'.format(self.next_file_number))
            self.next_file_number += 1
    
    # define global variable
    file_list = ['file_1', 'file_2', 'file_3']
    
    root = tk.Tk()
    mp = MainPage(root, None)
    mp.pack()  # MainPage is a widget, needs to have layout manager method called upon it
    root.mainloop()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-30
      • 2018-04-30
      • 2013-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多