【问题标题】:How to properly make OPEN and SAVE function with Tkinter?如何正确使用 Tkinter 进行 OPEN 和 SAVE 功能?
【发布时间】:2020-11-09 17:19:11
【问题描述】:

我正在制作一个简单的购物清单应用程序。 每当我尝试保存列表框shopping_list 中的内容时,它都会在函数创建的.txt 文件中保存为元组('.., .., ...,')

当我使用open 按钮时,listbox 将文本显示为tuple

例子:

如果在输入字段中我写了类似pizza 的内容并将其添加到listbox 并保存。当我尝试在listbox 中打开同一个文件时,listbox 现在显示:('pizza')。如何让列表框只显示pizza

代码:

from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
from PIL import ImageTk, Image


def add_item():
    '''
        This function takes the input from the entry field
        and places the item in a shopping list.

    :return: Adds to list
    '''

    if len(user_input.get()) == 0: # Checks if user typed into the entry field.
        messagebox.showwarning("Warning", "No keys were detected from the Entry field") # Send warning for no input.

    # Else statement for adding the user input to shopping list.
    else:
        shopping_list.insert(END, user_input.get())
        user_input.delete(0, END)  # Deletes whatever the user wrote in the entry box after button is clicked.


def remove_item():
    '''
        This function deletes the selected items when REMOVE button is clicked
    '''
    try:
        selected = shopping_list.curselection()
        for item in selected[::-1]:  # Fetches all selected items from shopping list
            shopping_list.delete(item)


    # Make a warning if the shopping list is empty or items are not selected when REMOVE button is clicked.
    except TclError:
        messagebox.showwarning("Warning", "The shopping list is either empty \nor you didn't select an item")


def open_list():
    '''
        This function opens an existing shopping list that was previously saved.
    :return: Opens older saved files.
    '''
    root.file = filedialog.askopenfilename(initialdir="./", title="Select a file",
                                           filetypes=(("Txt files", "*.txt"), ("All files", "*,*")))

    with open(root.file, "r") as file:
        data_content = file.read()
        shopping_list.delete(0, END)
        shopping_list.insert(END, data_content)


def save_file():
    '''
        This function saves the whole shopping list and writes the content to the "shopping_list.txt" file.
    :return: None
    '''
    text_file = filedialog.asksaveasfilename(defaultextension=".txt")
    try:
        with open(text_file, "w") as file:
            file.write(str(shopping_list.get(0, END)))
    except FileNotFoundError:
        messagebox.showinfo("Alert", "No file was saved")

# backup eldre løsning:
"""
def save_file():
    '''
        This function saves the whole shopping list and writes the content to the "shopping_list.txt" file.
    :return: None
    '''
    root.filename = filedialog.asksaveasfilename()
    with open("shopping_list.txt", "w") as f:
        for i in shopping_list.get(0, END):
            f.write(i+"\n")

"""



# Root files
root = Tk()
root.title("Skoleoppgave OBLIG 5")
root.iconbitmap('favicon.icns')
root.geometry("500x500")
root.resizable(0, 0)


# TODO: Entry  widget  ENTRY  1
# Creating an Entry widget so user can add items to shopping-list.
user_input = Entry(root, relief=SUNKEN)
user_input.pack()
user_input.place(x=250, y=20, anchor=N)


# Todo: Buttons widget ADD ITEM 2
# Make a Button-widget that adds the user input from entry field to the shopping list.
add_entry = Button(root, text="ADD ITEM", command=add_item, padx=10, pady=5)
add_entry.pack()
add_entry.place(x=158, y=57)



# Todo: Listbox  widget 4
# Creating Listbox for shopping list items
shopping_list = Listbox(root, selectmode=EXTENDED)
shopping_list.pack()
shopping_list.place(x=160, y=100)

"""
# Opens last saved shopping list when program starts.
try:
    read = open("shopping_list.txt","r")
    list_file = read.readlines()
    read.close()
    for data in list_file:
        shopping_list.insert(0, END, data)
except FileNotFoundError:
    read = open("shopping_list.txt","w")
"""


# Todo: Buttons widget REMOVE 3
# Make a Button-widget that deletes the selected item from shopping list
remove_entry = Button(root, text="REMOVE", command=remove_item, padx=10, pady=5)
remove_entry.pack()
remove_entry.place(x=160, y=285)


# Todo: Buttons widget OPEN 5
# Make a Button-widget that deletes the selected item from shopping list
open_file = Button(root, text="OPEN", command=open_list, padx=10, pady=5)
open_file.pack()
open_file.place(x=160, y=285)

# Todo: Buttons widget SAVE 6
# Make a Button-widget that deletes the selected item from shopping list
save_file = Button(root, text="SAVE", command=save_file, padx=10, pady=5)
save_file.pack()
save_file.place(x=282, y=57)

root.mainloop()

【问题讨论】:

  • 由于 Tkinter 的 Listbox get 方法返回一个元组(参见 here),因此它是这样编写的也就不足为奇了。这只是意味着您在加载文件时将值解析为元组。或者将每个项目写在自己的行或其他东西上,然后在读回时,在每个新行上拆分。解决问题的方法有很多,您只需要在读取文件数据时做出正确的假设,而您目前没有(即,将整个元组作为字符串传递,而不是从中解析出每个项目)。
  • 是的,感谢您的回答,但这是我在发布之前的想法。但实际我做不到。从应用程序打开文件时,我搜索了拆分元组的方法。但我似乎无法弄清楚。你写了解析?我不知道那是什么意思。就像我说的,我对此完全陌生。猜想我只需要谷歌更多。感谢您的回复。
  • 你通过get 得到一个元组,所以你可以把它写成不是一个元组,而是一个字符串列表,每个字符串之间有换行符、逗号或其他任何内容。然后你只需要在从文件中读取数据时做相反的事情。如果您对这样一个基本概念感到困惑,那么是的,我认为您需要做更多的谷歌搜索和教程(特别是文件输入/输出)。
  • 再次感谢戴维斯的回答。我目前攻读计算机科学学位 2 个月,所以是的,我确实需要了解更多信息。这基本上就是我现在想要做的。学习..

标签: python python-3.x tkinter


【解决方案1】:

如 cmets 中所述,您试图将字符串放入请求元组的方法中,这将产生错误。

因此,一种方法是添加读写功能,以将数据格式写入您自己控制的文件。提示正在尝试将您在列表框中看到的内容一对一地复制到文本文件中。看起来你的“eldre losning”会每行放一个项目。所以事情是读取文件,以便获得一个字符串列表,其中每一行都成为列表中的一个项目。提示....split 在字符串上的效果很好。

或者,只处理文件中已有的字符串。 一种方法是添加/修改以下内容。

from ast import literal_eval # added import for safe evals

# modified open
with open(root.file, "rt") as file:
    data_content = literal_eval(file.read())
    shopping_list.delete(0, END)
    shopping_list.insert(END, *data_content)

旁注#1,如果您使用.place,则不需要.pack()。 旁注#2,下一次,提到你正在做作业。 旁注#3,如果您使用此答案中的内容-您可能需要先阅读一下才能解释为什么可以这样做才能相信您自己想出了它:-)

祝你学习顺利。

【讨论】:

  • 你好,@ahed87!只是想跟进你的回答并告诉你我解决了这个问题,最后几个小时后。我最终采用了不同的方法。我更改了函数在保存文件时如何写入文件的方法。我使用 For 循环为每个对象添加一个逗号。并且以这种方式,当我使用 open 函数加载列表时,它现在为每个带有 COMMA 的 objekt 创建一个列表。所以现在它终于可以工作了,我不需要复制你的解决方案。谢谢回复!!
猜你喜欢
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
  • 1970-01-01
  • 2021-11-11
  • 2019-06-01
  • 1970-01-01
  • 2015-05-26
  • 1970-01-01
相关资源
最近更新 更多