保存两个选中的复选框,如果我打开和关闭 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()
我提出了一个包含两个复选框和一个按钮的小型 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()