是否将类集成到我现有的代码中? Tkinter,蟒蛇 3

如何解决是否将类集成到我现有的代码中? Tkinter,蟒蛇 3

我有这个 GUI 应用程序,我已经痴迷了一个多星期,我认为它比我迄今为止获得的有限编程/python 知识所能管理的要难一些 - 但是,我只能'不要停止思考它,我无法弄清楚它让我发疯。

我用 Tkinter 创建了一个 GUI,这是一个 Todo-list 应用程序。但是,应用程序中的每个任务都必须有一些与之相关的信息。

假设我们创建了一个名为“家庭作业”的任务。

我想将一些属性家庭作业相关联。

因此,其中一些属性将是 “影响”,它代表在 0-10 的范围内完成任务的影响(例如 10:如果我不这样做,我的课程就会失败) t 完成我的家庭作业任务。)和截止日期 - 这是不言自明的。这些只是我想要的 2 个属性(不过还会有更多)。

据我所知,这将是利用 classes 的好时机。

如果我理解正确,我将不得不创建一个 class Task:,然后将 Task 的每个实例的属性设置为某物。

我在熟悉类之前创建了 GUI,我想与给定任务关联的一些属性信息在创建任务后已经可以在 GUI 中指定(没有任何功能),但我不知道如何使用该信息并将其连接到给定的任务,以便它具有我想要的功能

我希望能够输入一个任务,指定一些与该任务相关的属性,然后我希望能够“召唤”该任务及其相关属性以进行一些简单的数学和/或排序。 我只希望用户看到该任务本身 - 计算/排序将在幕后进行。

我的问题: 我应该用类来做这件事,还是有一种更初级的方法可以更容易地实现到我现有的代码中? 我真的,真的很想弄清楚如何解决这个问题,因此任何合格的指示或正确的方向或示例、解释等都将受到真正的赞赏。

这是我的代码

from tkcalendar import *
import tkinter.messageBox # Import the messageBox module
import pickle # Module to save to .dat
import tkinter as tk

TASKS_FILE = "tasks.dat" ##Where the task strings are saved
task_list = [] ##Don't kNow what I am doing yet
impact_number = []  ##Don't kNow if this Could be useful

root = tk.Tk() # ?????
root.title('SmaTodo') # Name of the program/window
# ROOT WINDOW
# Gets the requested values of the height and widht.
windowWidth = root.winfo_reqwidth()
windowHeight = root.winfo_reqheight()
 
# Gets both half the screen width/height and window width/height
positionRight = int(root.winfo_screenwidth()/2 - windowWidth/2)
positionDown = int(root.winfo_screenheight()/2 - windowHeight/2)
 
# Positions the window in the center of the page.
root.geometry("+{}+{}".format(positionRight,positionDown))


def new_task():
    def add_task():
        global task
        global impact_window
        task = entry_task.get() # we get the task from entry_task and we get the input from the entry_task type-field with .get()
        if task != '': # If textBox inputfield is NOT empty do this:
            listBox_tasks.insert(tkinter.END,task)
            entry_task.delete(0,tkinter.END) # 
            task_window.destroy()
        else:
            tkinter.messageBox.showwarning(title='Whoops',message='You must enter a task')
            task_window.destroy()
    
    task_window = tk.Toplevel(root)
    task_window.title('Add a new task')
    task_label = tk.Label(task_window,text = 'Title your task concisely:',justify='center')
    task_label.pack()
    # Entry for tasks in new window
    entry_task = tk.Entry(task_window,width=50,justify='center')
    entry_task.pack()
    # Add task button in new window
    button_add_task = tk.Button(task_window,text='Add task',width=42,command=lambda: [add_task(),impact()])
    button_add_task.pack()



def impact():
        global impact_next_button
        global impact_window
        global impact_label
        global impact_drop
        global options
        global select

        impact_window = Toplevel(root)
        impact_window.title('Impact')
        options = StringVar()
        options.trace_add
        task_label = tk.Label(impact_window,text=str(task),font='bold')
        task_label.pack()
        impact_label = tk.Label(impact_window,text = 'Specify below the impact of completing this task \n (10 being the highest possible impact)',justify='center')
        impact_label.pack()
        impact_drop = OptionMenu(impact_window,options,'0','1','2','3','4','5','6','7','8','9','10')
        impact_drop.pack()
        impact_next_button = tk.Button(impact_window,text='Next',command=connectivity)
        impact_next_button.pack(side=tkinter.RIGHT)
        def select():
            global impact_next_button
            global impact_window
            global impact_label
            global impact_drop
            global options
            impact_number.append(str(task) + options.trace_add('write',lambda *args: print(str(task)+' '+ 'impact' + ' ' + options.get())))
            options.set(options.get())
        
    

     
def connectivity():
    impact_window.destroy()
    clicked = StringVar()
    clicked.set('Select')
    global connectivity_next_button
    global connectivity_window
    global connectivity_label
    global connectivity_drop
    connectivity_window = Toplevel(root)
    connectivity_window.title('Connectivity')
    task_label = tk.Label(connectivity_window,font='bold')
    task_label.pack()
    connectivity_label = tk.Label(connectivity_window,text = 'Specify below the connectivity this task has to other tasks\n (e.g. tasks you can not complete unless you have completed this task)',justify='center')
    connectivity_label.pack()
    # var1 = Intvar()
    Checkbutton(connectivity_window,text="Each task from list must be 'checkable' in this window").pack() # variable=var1).pack()

    connectivity_next_button = tk.Button(connectivity_window,command=lambda: [Proximity(),select()])
    connectivity_next_button.pack(side=tkinter.RIGHT)

def Proximity():
    connectivity_window.destroy()
    global proximity_button
    global proximity_window
    global proximity_label
    global proximity_drop
    global cal
    global proximity_output_date
    proximity_window = Toplevel(root)
    proximity_window.title('Proxmity')
    task_label = tk.Label(proximity_window,font='bold')
    task_label.pack()
    proximity_label = tk.Label(proximity_window,text = 'Specify a deadline for when this task must be completed',justify='center')
    proximity_label.pack()
    cal = Calendar(proximity_window,selectmode='day',year=2021,month=4,day=27)
    cal.pack()
    def get_date():
        proximity_output_date.config(text=cal.get_date())
    proximity_date_button = tk.Button(proximity_window,text='Pick date',command=get_date)
    proximity_date_button.pack()
    proximity_output_date = tk.Label(proximity_window,text='')
    proximity_output_date.pack()
    proximity_button = tk.Button(proximity_window,command=manageability)
    proximity_button.pack(side=tkinter.RIGHT)

def manageability():
    print('Deadline:'+' '+cal.get_date())
    proximity_window.destroy()
    clicked = StringVar()
    clicked.set('Select')
    global manageability_next_button
    global manageability_window
    global manageability_label
    global manageability_drop
    manageability_window = Toplevel(root)
    manageability_window.title('Manageability')
    task_label = tk.Label(manageability_window,font='bold')
    task_label.pack()
    manageability_label = tk.Label(manageability_window,text = 'Specify how difficult this task is to complete \n (0 being extremely difficult and 10 being extremely easy)',justify='center')
    manageability_label.pack()
    manageability_drop = OptionMenu(manageability_window,clicked,'10')
    manageability_drop.pack()
    manageability_next_button = tk.Button(manageability_window,command=urgency)
    manageability_next_button.pack(side=tkinter.RIGHT)

def urgency():
    pass
    



def delete_task():
    try:
        task_index = listBox_tasks.curselection()[0]
        listBox_tasks.delete(task_index)
    except:
        tkinter.messageBox.showwarning(title='Oops',message='You must select a task to delete')

def save_tasks():
    tasks = listBox_tasks.get(0,listBox_tasks.size())
    pickle.dump(tasks,open('tasks.dat','wb'))




# Create UI
your_tasks_label = tk.Label(root,text='THESE ARE YOUR TASKS:',font=('Roboto',10,'bold'),justify='center')
your_tasks_label.pack()

frame_tasks = tkinter.Frame(root)
frame_tasks.pack()

scrollbar_tasks = tkinter.Scrollbar(frame_tasks)
scrollbar_tasks.pack(side=tkinter.RIGHT,fill=tkinter.Y)

listBox_tasks = tkinter.ListBox(frame_tasks,height=10,10),justify='center') # tkinter.ListBox(where it should go,height=x,width=xx)
listBox_tasks.pack()

listBox_tasks.config(yscrollcommand=scrollbar_tasks.set)
scrollbar_tasks.config(command=listBox_tasks.yview)


try:
    tasks = pickle.load(open('tasks.dat','rb'))
    listBox_tasks.delete(0,tkinter.END)
    for task in tasks:
        listBox_tasks.insert(tkinter.END,task)
except:
    tkinter.messageBox.showwarning(title='Phew',message='You have no tasks')

# Add task button
button_new_task = tkinter.Button(root,text='New task',command=new_task)
button_new_task.pack()


button_delete_task = tkinter.Button(root,text='Delete task',command=delete_task)
button_delete_task.pack()


button_save_tasks = tkinter.Button(root,text='Save tasks',command=save_tasks)
button_save_tasks.pack()



















root.mainloop() # Runs the program - must be at the very buttom of the code

这里的一些人已经帮了我很多,我真的很感激。

解决方法

所以我做了一些示例代码:

from tkinter import Tk,Frame,Button,Entry,Label,Canvas,Scrollbar,OptionMenu,Toplevel,StringVar
import pickle


class Task:
    def __init__(self,name,type_,importance):
        self.name = name
        self.type = type_
        self.importance = importance


try:
    with open('saved_tasks.dat','rb') as file:
        task_list = pickle.load(file)

except FileNotFoundError and EOFError:
    with open('saved_tasks.dat','w') as file:
        pass
    print('Could not locate the file or the file was empty. A new file was created.')
    task_list = []

task_types = ['Misc','Math','Science','Economics','Biology','Homework']


def show_tasks():
    for widget in task_frame.winfo_children():
        widget.destroy()

    for task in task_list:
        Label(task_frame,text=f'{task.name} | Type: {task.type} | Importance: {task.importance}').pack(fill='x')


def open_add_task():
    win = Toplevel(root)
    win.focus_force()

    Label(win,text='Write task name').grid(column=0,row=0)
    Label(win,text='Choose type of task').grid(column=1,text='Choose importance of task').grid(column=2,row=0)

    entry = Entry(win)
    entry.grid(column=0,row=1,sticky='ew')

    type_var = StringVar(value=task_types[0])
    OptionMenu(win,type_var,*task_types).grid(column=1,sticky='nsew')

    imp_var = StringVar(value=1)
    OptionMenu(win,imp_var,*range(1,10+1)).grid(column=2,sticky='nsew')

    def add_task():
        task_list.append(Task(entry.get(),type_var.get(),imp_var.get()))
        show_tasks()

    Button(win,text='Add Task',command=add_task).grid(column=0,row=2,columnspan=3,sticky='nsew')


def sort_tasks():
    type_ = sort_type.get()
    importance = sort_imp.get()
    order = asc_desc_var.get()

    for widget in task_frame.winfo_children():
        widget.destroy()

    for task in task_list if order == 'Ascending' else task_list[::-1]:
        if type_ == 'All' and importance == 'Any':
            Label(task_frame,text=f'{task.name} | Type: {task.type} | Importance: {task.importance}').pack(fill='x')
        elif type_ == 'All':
            if importance == task.importance:
                Label(task_frame,text=f'{task.name} | Type: {task.type} | Importance: {task.importance}').pack(fill='x')
        elif type_ != 'All':
            if type_ == task.type and importance == 'Any':
                Label(task_frame,text=f'{task.name} | Type: {task.type} | Importance: {task.importance}').pack(fill='x')
            elif type_ == task.type and importance == task.importance:
                Label(task_frame,text=f'{task.name} | Type: {task.type} | Importance: {task.importance}').pack(fill='x')


root = Tk()

btn_frame = Frame(root)
btn_frame.pack(fill='x')

sort_type = StringVar(value='All')
OptionMenu(btn_frame,sort_type,'All',*task_types).grid(column=0,row=0,sticky='nsew')

sort_imp = StringVar(value='Any')
OptionMenu(btn_frame,sort_imp,'Any',10+1)).grid(column=1,sticky='nsew')

asc_desc_var = StringVar(value='Ascending')
OptionMenu(btn_frame,asc_desc_var,'Ascending','Descending').grid(column=2,sticky='nsew')

Button(btn_frame,text='Sort',command=sort_tasks).grid(column=0,text='Add New',command=open_add_task).grid(column=3,rowspan=2,sticky='nsew')

task_frame_main = Frame(root)
task_frame_main.pack()

task_frame = Frame()
canvas = Canvas(task_frame_main)
canvas.pack(side='left',expand=True,fill='both')
canvas.create_window((0,0),window=task_frame,tag='task_frame',anchor='nw')
scrollbar = Scrollbar(task_frame_main,orient='vertical',command=canvas.yview)
scrollbar.pack(side='right',fill='y')
canvas.config(yscrollcommand=scrollbar.set)
canvas.bind('<Configure>',lambda e: canvas.config(scrollregion=canvas.bbox('task_frame')))

show_tasks()

root.mainloop()

try:
    with open('saved_tasks.dat','wb') as file:
        pickle.dump(task_list,file)
        print('File saved.')

except Exception as e:
    print(f'Exception was raised:\n{e}')

这里的主要部分是 Task 类,因为您可以看到它非常小,这就是重点,它不必太大。并且 task_list 可以使用 pickle 轻松序列化并且易于加载,并且它会保留那些具有给定属性的类。

如果您有任何其他问题,请提问。

解释一切(或至少解释大部分):

首先导入您需要的所有内容,我喜欢在使用 tkinter 时这样做。

然后我定义了 task_list 它将用于存储添加的任务,这可以并且可能应该由文件替换,因此您可以读取文件,然后将保存的任务附加到此列表中或仅使用 json或 pickle 将文件作为列表导入,这样更容易。无论如何,然后我刚刚创建了一个列表来存储所有类型的任务,它可以修改,这又不是必需的,但是可以从文件中加载列表,例如,如果有添加另一种类型的选项(这需要相当多的编码)将它们保存到文件中以便保存信息会很棒。

现在关于class Task
这个类没有很多属性,实际上只有三个来存储基本的东西,比如任务的name、任务的type以及它的重要性。

这里没有太多内容,但要提到的是,可以使用例如 pickle 模块并将其应用于 task_list(将存储 Task 的实例),它将序列化这个对象,同时保留它的属性,所以当从 pickle 加载时,仍然可以以相同的方式访问该对象。

现在转到 show_tasks() 函数。
所以这是一个通用函数,用于显示附加到 task_list 也就是所有任务的所有内容。此函数将 Label 放在下面指定的框架上,但首先它会删除该框架外的所有内容,否则它每次都会附加所有项目,这意味着它将呈指数增长(您可以通过删除第一个来测试您是否想要循环并添加一些任务)。

接下来是 open_add_task() 函数,用于添加任务。
它首先创建另一个窗口 Toplevel 并将焦点放在它上面。 (有时我喜欢bind这样的窗口,这样当用户点击窗口外并且这个窗口失去焦点时关闭它,这样就不会有多个这样的窗口,但这取决于你)。

然后我创建了一些标签来帮助用户指出他们的要求。

然后我放置了条目,以便用户可以输入任务名称,然后为了避免用户输入错误,我让他们选择他们想要的类别和重要性,以免他们输入错误。

然后我定义了一个函数 (add_task()),用于从用户输入中收集数据、创建类实例并将其附加到 task_list。并以创建一个调用此函数的 Button 结束。

进入sort_tasks 此功能与根上的小部件链接,因此有参考。所以首先获取用户输入的内容并存储在变量中以便于重用。同样,通过提供选择,用户输入变得更容易。再次清除所有小部件,然后是排序/逻辑部分,这可能可以改进,我没有添加按重要性数字排序的选项(所以它有多高)所以它按添加的时间排序(同样没有确切的时间但只是列表中的顺序是添加的时间)。逻辑可以改进,但它主要做它应该做的事情(已经晚了,我无法正确思考)但是是的,没有太多可以解释的,只需自己逐步完成即可。

下一位是主窗口,它不在任何函数内,不使用global。首先我启动了 Tk() 这是基本的,最后使用了 .mainloop() - 基本的东西。然后有很多框架用于帮助组织小部件,然后添加所有小部件在这种情况下我说的是有助于 sort_tasks() 功能的小部件。因此添加了所有选择菜单和执行 sort_tasks 的按钮。还有一个调用 open_add_task() 的按钮。

下一位是显示所有任务的主框架。画布很重要,因为 Frame 本身不能滚动,而画布可以滚动,所以本质上会发生什么,是一个框架被添加到画布并且 scrollregion 被设置为 { {1}} 大小。然后添加滚动条(将添加链接)。

仅此而已。

编辑: 添加了保存和读取文件的功能,以便可以保存和加载任务。出于某种原因,文件必须在 Frame 之后加载,因为显然否则它会抛出一个我不完全理解的错误,但我通过将类移到整个事情之上来处理它。我还发现了一个问题,当添加新任务并且它们超过可见帧限制时,滚动条不起作用,但是再次打开文件它可以正常工作,因此可以处理。同样如您所见,我在 Task 之后添加了保存功能,以便每当用户关闭窗口时,它都会将任务保存到文件中。 (添加到来源)

来源:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?