保存两个选中的复选框,如果我打开和关闭 window(可执行示例)

Save two selected checkboxes, if i open and close the window (executable example)

我提出了一个包含两个复选框和一个按钮的小型 executable 示例。目标是保存组合框的 selection / 检查,以便关闭 window 然后重新打开它以找到 selected 框。我希望能够选择 select 一个或所有复选框,因为我想避免在重新打开 window 时重新加载所有复选框的问题,但我只想重新加载 select编的。

我建立了与 Sql 的连接,创建了一个 table 并且值被正确保存。数据库里自动存了1,不知道对不对。但是,如果我关闭并重新打开 window,复选框将不再 selected。

你能告诉我回复可以做什么吗?我是 Python 的新手,如果你只是发表评论我可能不明白。谢谢

import sqlite3
from tkinter import *
from tkinter import ttk
import tkinter as tk
import tkinter.messagebox
from tkinter import messagebox

root=tk.Tk()
root.geometry("200x200")
root.configure(bg='white')

Checkbutton1 = IntVar() 
Checkbutton2 = IntVar() 

#button 1            
Button1 = Checkbutton(root, text = "Checkbox 1", variable = Checkbutton1, onvalue = 1, offvalue = 0, height = 1,
                      bg="white", foreground='black', activebackground="white") #command=Button1_func)
Button1.place(x=10, y=36)

#button 2
Button2 = Checkbutton(root, text = "Checkbox 2", variable = Checkbutton2, onvalue = 1, offvalue = 0, height = 1,
                      bg="white", foreground='black', activebackground="white") #command=Button1_func)
Button2.place(x=10, y=56)
            

def save():
    value_Button1 = Checkbutton1.get()
    value_Button2 = Checkbutton2.get()
                
    if Checkbutton1.get() =="" or Checkbutton2.get() =="":
       tkinter.messagebox.showerror("Select checkbox")

    else:
        conn = sqlite3.connect("...")
        c = conn.cursor()

        c.execute("UPDATE table_checkbox SET Button1 =? Button=? WHERE id =1;", (value_Button1,), (value_Button2,))
        conn.commit()
        conn.close()
        messagebox.showinfo("Saved successfully")

             
#Button save
save = Button(root, text="Save", bg='#b40909', foreground='white', command= save)
save.pack()
save.place(x=10, y=80)

root.mainloop()

示例数据库

CREATE TABLE "table_checkbox" (
    "id"    INTEGER,
    "Button1"   INTEGER,
    "Button2"   INTEGER,
    PRIMARY KEY("id" AUTOINCREMENT)
);

以下代码执行复选框值的初始化、保存和加载,但如果调用 save 时未选中复选框,保存函数(基本上是从您的示例中获取的)会导致错误。但这不是问题的一部分,我留给你自己解决。


import os
import sqlite3
from tkinter import *
from tkinter import ttk
import tkinter as tk
import tkinter.messagebox
from tkinter import messagebox

def init_db():
    conn = sqlite3.connect("GUI_state.db")
    c = conn.cursor()
    c.execute("create table table_checkbox (id integer, button_value integer, PRIMARY KEY('id' AUTOINCREMENT));")
    c.execute("insert into table_checkbox (button_value) values (0)")
    conn.commit()
    conn.close()


def save():
    value_Button1 = Checkbutton1_var.get()
    if Checkbutton1_var.get() == "":
        tkinter.messagebox.showerror("Select checkbox")
    else:
        conn = sqlite3.connect("GUI_state.db")
        c = conn.cursor()
        c.execute(f"UPDATE table_checkbox SET button_value = {value_Button1} WHERE id=1;")
        conn.commit()
        conn.close()
        messagebox.showinfo("Saved successfully")


def load():
    conn = sqlite3.connect("GUI_state.db")
    c = conn.cursor()
    button_val = c.execute("SELECT button_value FROM table_checkbox WHERE id=1;")
    button_val = tuple(button_val)[0]
    conn.close()
    return button_val


if __name__ == "__main__":
    if not os.path.exists("GUI_state.db"):
        init_db()
    root = tk.Tk()
    root.geometry("200x200")
    root.configure(bg='white')

    value = load()
    Checkbutton1_var = IntVar(value=value)

    Button1 = Checkbutton(root, text="Checkbox 1", variable=Checkbutton1_var, onvalue=1, offvalue=0,
                          height=1,
                          bg="white", foreground='black',
                          activebackground="white")
    Button1.place(x=10, y=36)

    # Button save
    save = Button(root, text="Save", bg='#b40909', foreground='white', command=save)
    save.pack()
    save.place(x=10, y=80)

    root.mainloop()

这里有不同的事情要记住,首先是你不需要检查 Checkbutton1 的值,然后只有当它是 "" 时才插入,因为它永远不会是 "",因为它是一个整数,永远不会是一个字符串。

如果 table 中没有记录,你需要在这里插入状态,如果有记录,则更新记录,这是因为你 ID 为 PRIMARY KEY。

自从您编辑了问题后,您不再要求案例答案,而是一般答案。在示例中,我创建了 i 复选框,最后我将 i 值保存到数据库中,并在重新启动时读取这些值 i 次并追加回复选框。

该示例从数据库中读取数据并更新列表中的项目。所以重要的是你在创建它们时将每个相关的 IntVar 添加到列表中。

import sqlite3
import tkinter as tk
from tkinter import messagebox

root = tk.Tk()
root.geometry("200x200")
root.configure(bg='white')

chk_lst = []
for i in range(5):
    chk_var = tk.IntVar() 
    tk.Checkbutton(root, text=f"Checkbox {i+1}", variable=chk_var, onvalue=1,
                        offvalue=0, height=1, bg="white", foreground='black',
                        activebackground="white").grid(row=i,column=0)
    chk_lst.append(chk_var)

# CREATE EXTRA CHECKBOXES WITHOUT LOOP
var1 = tk.IntVar()
tk.Checkbutton(root, text=f"Checkbox {i+2}", variable=var1, onvalue=1,
                        offvalue=0, height=1, bg="white", foreground='black',
                        activebackground="white").grid(row=i+1,column=0) #i+1 or whatever row you like
var2 = tk.IntVar()
tk.Checkbutton(root, text=f"Checkbox {i+3}", variable=var2, onvalue=1,
                        offvalue=0, height=1, bg="white", foreground='black',
                        activebackground="white").grid(row=i+2,column=0) 

chk_lst.extend([var1,var2])

def save():
    conn = sqlite3.connect("save.db")
    c = conn.cursor()
    
    for idx,chk_btn in enumerate(chk_lst,start=1):
        c.execute(f'SELECT button1 FROM table_checkbox WHERE id=?',(idx,))
        rec = c.fetchall()

        if rec:
            c.execute("UPDATE table_checkbox SET Button1=? WHERE id=?;", (chk_btn.get(),idx))
        else:
            c.execute("INSERT INTO table_checkbox VALUES (?,?);", (idx,chk_btn.get()))
        
    conn.commit()
    conn.close()

    messagebox.showinfo("Saved successfully","Saved successfully")

def load():
    conn = sqlite3.connect("save.db")
    c = conn.cursor()
    c.execute("SELECT * FROM table_checkbox")
    vals = c.fetchall()
    
    for val,chk_btn in zip(vals,chk_lst):
        chk_btn.set(val[1])
    
    conn.close()

def create():
    conn = sqlite3.connect("save.db")
    c = conn.cursor()
    c.execute("""
    CREATE TABLE "table_checkbox" (
    "id"    INTEGER,
    "Button1"   INTEGER,
    PRIMARY KEY("id" AUTOINCREMENT));
    """)
    conn.close()

tk.Button(root, text="Save", bg='#b40909', foreground='white',
                command=save).grid(row=i+1,column=0)

try:
    load()
except sqlite3.OperationalError:
    create()

root.mainloop()

注意:即使您从代码中删除 1 个复选框,它也会存储在数据库中,但不会显示在 GUI 中,因为我实现了 zip。所以你可能想创建一个 clean_up 函数 itertools.zip_longest 来删除 GUI 关闭后未使用的额外复选按钮。

from itertools import zip_longest

...
...

def clean_up():
    conn = sqlite3.connect("save.db")
    c = conn.cursor()
    c.execute("SELECT * FROM table_checkbox")
    vals = c.fetchall()

    for val,chk_box in zip_longest(vals,chk_lst):
        if chk_box is None: # If there is an extra item in the database that is not there in the list, remove the item from the database.
            idx = val[0]
            c.execute('DELETE FROM table_checkbox WHERE id=?',(idx,))
            conn.commit()

    conn.close()

...
...
root.mainloop()
clean_up()