【问题标题】:Checkbox variable not updating in tkinter复选框变量未在 tkinter 中更新
【发布时间】:2019-11-13 04:49:35
【问题描述】:

我对 Tkinter 有点陌生。我在 Windows x64 上运行 Python 3.7.4。我正在尝试制作一个简单的复选框驱动菜单,该菜单将根据复选框传递某些值。这是代码:

main.py

import sqlite3
import os
from cryptography.fernet import Fernet

path = r"C:\Users\anves\PycharmProjects\pwdatabase\pwprotect.db"


def dbcreate():
    db = sqlite3.connect('pwprotect.db')
    csr = db.cursor()
    csr.execute("CREATE TABLE INFO(SITENAME TEXT, USERNAME TEXT, PASSWORD TEXT, PWKEY TEXT)")


if not os.path.exists(path):
    dbcreate()

db = sqlite3.connect('pwprotect.db')


def home():
    print("Welcome to Password Database!")
    print()
    print("1. Make a new entry")
    print("2. Search in existing entries")
    print("3. Update an existing entry")
    ch = int(input("Enter your choice: "))
    print()
    if ch == 1:
        insert()
    if ch == 2:
        search()
    if ch == 3:
        update()


def insert(sitename, username, password):
    while True:
        '''
        print()
        sitename = input("Enter the name of the site: ").lower()
        username = input("Enter your username for the site: ")
        password = ""
        ch = input("Do you want to use our generated password?(y/n): ")
        if ch == "y":
            password = pwgenerator()
            print("Your generated password is ", password)
        elif ch == "n":
            password = input("Enter your password for the site: ")
'''
        enk, key = encrypt(password)
        entities = (sitename, username, enk, key)
        cursor = db.cursor()
        cursor.execute('INSERT INTO INFO(SITENAME,USERNAME,PASSWORD,PWKEY) VALUES (?,?,?,?)', entities)
        db.commit()
        '''
        ch = input("Do you want to make another entry?(y/n): ")
        if ch == 'n':
            ch = input("Do you want to return to home screen?(y/n): ")
            print()
            if ch == 'y':
                home()
                break

            elif ch == 'n':
                print("Thank you for using Password Database")
                return

        elif ch == 'y':
            continue

        else:
            print("Invalid input")
            home()
            break
'''
        break
    return


def search(site):
    while True:
        # site = input('Enter the name of the site: ').lower()
        csr = db.cursor()
        csr.execute('SELECT USERNAME, PASSWORD, PWKEY FROM INFO WHERE SITENAME == ?', (site,))
        row = csr.fetchone()
        if row is not None:
            username = row[0]
            enk = row[1]
            key = row[2]
        else:
            # print("Data not found")
            # home()
            return "not found", "not found"

        password = decrypt(enk, key)
        '''
        print()
        print("Username: ",username)
        print("Password: ",password)

        ch = input("Do you want to search again?(y/n): ")
        if ch == 'n':
            ch = input("Do you want to return to home screen?(y/n): ")
            print()
            if ch == 'y':
                home()
                break

            elif ch == 'n':
                print("Thank you for using Password Database")
                return

        elif ch == 'y':
            continue

        else:
            print("Invalid input")
            home()
            break
            '''
        break
    return username, password


def update(site, user, passw):
    while True:
        # site = input('Enter the name of the site: ').lower()
        # ch = int(input("1 = Change Username, 2 = Change Password: "))
        csr = db.cursor()
        if passw is None:
            # user = input("Enter new username: ")
            csr.execute('UPDATE INFO SET USERNAME = ? WHERE SITENAME = ?', (user, site))
            db.commit()
            # print("Your new username is ", user)

        elif site is None:
            # passw = ""
            # c = input("Do you want to use our generated password?(y/n): ")
            '''
            if c == "y":
                passw = pwgenerator()
            elif c == "n":
                passw = input("Enter new password: ")
            '''
            enk, key = encrypt(passw)

            csr.execute('UPDATE INFO SET PASSWORD = ? WHERE SITENAME = ?', (enk, site))
            csr.execute('UPDATE INFO SET PWKEY = ? WHERE SITENAME = ?', (key, site))
            db.commit()
            # print("Your new password is ", passw)

        else:
            enk, key = encrypt(passw)
            csr.execute('UPDATE INFO SET USERNAME = ? WHERE SITENAME = ?', (user, site))
            csr.execute('UPDATE INFO SET PASSWORD = ? WHERE SITENAME = ?', (enk, site))
            csr.execute('UPDATE INFO SET PWKEY = ? WHERE SITENAME = ?', (key, site))
            db.commit()
        '''
        else:
            print("Invalid input")
            home()
            break

        ch = input("Do you want to update again?(y/n): ")

        if ch == 'n':
            ch = input("Do you want to return to home screen?(y/n): ")
            print()
            if ch == 'y':
                home()
                break

            elif ch == 'n':
                print("Thank you for using Password Database")
                return

        elif ch == 'y':
            continue

        else:
            print("Invalid input")
            home()
            break
        '''
        break


def pwgenerator():
    import random
    pw = ""
    lower = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
             "v", "w", "x", "y", "z"]
    upper = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
             "V", "W", "X", "Y", "Z"]
    digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
    special = ["@", "%", "+", '/', "!", "#", "$", "^", "?", ":", ",", ".", "_", "-"]
    i = 0
    while i <= 15:
        n = random.randint(0, 4)
        if n == 1:
            pw = pw + random.choice(lower)
        elif n == 2:
            pw = pw + random.choice(upper)
        elif n == 3:
            pw = pw + random.choice(digits)
        elif n == 4:
            pw = pw + random.choice(special)
        i += 1
    print(pw)
    return pw


def encrypt(pw):
    key = Fernet.generate_key()
    f = Fernet(key)
    b = bytes(pw, 'utf-8')
    encoded = f.encrypt(b)
    return encoded, key


def decrypt(enk, key):
    f = Fernet(key)
    decoded = f.decrypt(enk)
    pw = str(decoded.decode('utf-8'))
    return pw

gui.py

from tkinter import messagebox
import tkinter
import main

win1 = tkinter.Tk()
win1.geometry("500x200")
win1.title("Password Database")
l1 = tkinter.Label(win1, text="Welcome to Password Database!").grid(row=0, column=0)
l2 = tkinter.Label(win1, text="").grid(row=1, column=0)
entry = tkinter.Label(win1, text="1. Make a new entry")
entry.grid(row=2, column=0)
search = tkinter.Label(win1, text="2. Search for an existing entry")
search.grid(row=3, column=0)
update = tkinter.Label(win1, text="3. Update an existing entry")
update.grid(row=4, column=0)
choice = tkinter.Entry(win1, width=10)
choice.grid(row=5, column=0)


def entrygui():
    wini = tkinter.Tk()
    wini.geometry("500x200")
    wini.title("New Entry")
    entryl1 = tkinter.Label(wini, text="Enter name of the site: ")
    entryl2 = tkinter.Label(wini, text="Enter your username for the site: ")
    entryl3 = tkinter.Label(wini, text="Enter the password the site: ")
    entrye1 = tkinter.Entry(wini, width=20)
    entrye2 = tkinter.Entry(wini, width=20)
    entrye3 = tkinter.Entry(wini, width=20)
    entryl1.grid(row=0, column=0)
    entryl2.grid(row=1, column=0)
    entryl3.grid(row=2, column=0)
    entrye1.grid(row=0, column=1)
    entrye2.grid(row=1, column=1)
    entrye3.grid(row=2, column=1)

    def insertbt():
        site = str(entrye1.get())
        user = str(entrye2.get())
        passw = str(entrye3.get())
        main.insert(site, user, passw)
        messagebox.showinfo("Success!", "Entry added!")
        wini.destroy()

    insert = tkinter.Button(wini, text="Insert", command=insertbt)
    insert.grid(row=3, column=0)

    wini.mainloop()


def searchgui():
    wins = tkinter.Tk()
    wins.geometry("500x200")
    wins.title("Search")
    searchl1 = tkinter.Label(wins, text="Enter the name of the site: ")
    searchl1.grid(row=0, column=0)
    searche1 = tkinter.Entry(wins, width=20)
    searche1.grid(row=0, column=1)

    def searchbt():
        site = str(searche1.get())
        user, passw = main.search(site)
        messagebox.showinfo("Success!", "Username is "+user+"\nPassword is "+passw)
        wins.destroy()

    searchbtn = tkinter.Button(wins, text="Search", command=searchbt)
    searchbtn.grid(row=1, column=0)

    wins.mainloop()


def updategui():
    winu = tkinter.Tk()
    winu.geometry("500x200")
    winu.title("Update")
    caution = tkinter.Label(winu, text="Please select the option if you are updating the corresponding value")
    caution.grid(row=0, column=0)
    sitel = tkinter.Label(winu, text="Enter site name: ")
    sitee = tkinter.Entry(winu, width=20)
    userv = tkinter.IntVar()
    userr = tkinter.Checkbutton(winu, text="New Username: ", variable=userv)
    passv = tkinter.IntVar()
    passr = tkinter.Checkbutton(winu, text="New Password: ", variable=passv)
    usere = tkinter.Entry(winu, width=20)
    passe = tkinter.Entry(winu, width=20)
    sitel.grid(row=1, column=0)
    sitee.grid(row=1, column=1)
    userr.grid(row=2, column=0)
    usere.grid(row=2, column=1)
    passr.grid(row=3, column=0)
    passe.grid(row=3, column=1)

    def updatebt():
        userval = int(userv.get())
        passval = int(passv.get())
        print(userval, passval)
        site = str(sitee.get())
        if userval == 1 and passval == 0:
            user = str(usere.get())
            passw = None
            main.update(site, user, passw)
            messagebox.showinfo("Success", "Username updated")
            winu.destroy()
        elif userval == 0 and passval == 1:
            user = None
            passw = passe.get()
            main.update(site, user, passw)
            messagebox.showinfo("Success", "Password updated")
            winu.destroy()
        elif userval == 1 and passval == 1:
            user = str(usere.get())
            passw = str(usere.get())
            main.update(site, user, passw)
            messagebox.showinfo("Success", "Username and password updated")
            winu.destroy()
        elif userval == 0 and passval == 0:
            messagebox.showinfo("Error", "Please check a box")

    updatebtn = tkinter.Button(winu, text="Update", command=updatebt)
    updatebtn.grid(row=4, column=0)

    winu.mainloop()


def choicefn():
    ch = int(choice.get())
    if ch == 1:
        entrygui()
    elif ch == 2:
        searchgui()
    elif ch == 3:
        updategui()
    else:
        messagebox.showinfo("ERROR", "Please enter a valid choice")


submit = tkinter.Button(win1, text="Submit", command=choicefn).grid(row=5, column=1)
win1.mainloop()

updategui() 函数有问题。复选框值未更新。

输出始终为 0,0 并显示相应的错误框。 我写的并行代码没有这样的问题:

import tkinter
from tkinter import Checkbutton
win = tkinter.Tk()
v1 = tkinter.IntVar()
v1.set(0)
v2 = tkinter.IntVar()
v2.set(0)
c1 = tkinter.Checkbutton(win, text="mf", variable=v1)
c1.grid(row=0,column=0)
c2 = tkinter.Checkbutton(win, text="yeet", variable=v2)
c2.grid(row=1,column=0)
def btfn():
    i1 = (v1.get())
    i2 = (v2.get())
    print(i1,i2)
bt = tkinter.Button(win, text="Display",command=btfn)
bt.grid(row=2,column=0)
win.mainloop()

任何帮助将不胜感激! (P.S. 我把'e'放在变量名的末尾表示条目,'l'表示标签等)

【问题讨论】:

  • 当我运行你的代码时,什么也没有发生。如果我添加import tkinterupdategui(),我得到NameError: name 'userr' is not defined。您能否仔细检查并确认您正在运行的代码与您在此处提供的代码 100% 相同?
  • 也许你可以减少这里的代码量来显示你遇到的问题。
  • @Kevin 对不起,这是我的错字,只需将“userc”更改为“userr”。我已经编辑了问题中的代码
  • @quamrana 这是精简版,实际代码长 200 行。问题出在 CheckButton,或者更具体地说,变量 userr 和 userv
  • usere.grid(row=2, column=1) passr.grid(row=3, column=0) , usere 和 passr 没有定义

标签: python python-3.x variables tkinter checkbox


【解决方案1】:

我不能 100% 确定为什么会发生这种情况,但这是我根据实验得出的最佳猜测。

IntVar 的构造函数接受一个可选参数,如果提供的话,它应该是一个 Tk 实例。如果您不提供值,它将使用首先创建的任何 Tk。在您的情况下,win1 对象。

只要 Tk 实例有机会清除其事件队列,IntVar 就会自行更新。但这是一个问题——当您的winu 窗口正在运行时,您的win1 窗口会挂起,并且没有机会更新您的 IntVars。

或者可能窗口没有挂起,但它只是忽略了不属于它的小部件对其 IntVar 所做的更改。 userrpassrwinu 所有,因此 win1 选择不(或不能)听它们。

一种可能的解决方案是向您的 IntVar 提供 winu,这样他们就不会默认使用您的 win1 对象。

userv = tkinter.IntVar(winu)
userr = tkinter.Checkbutton(winu, text="New Username: ", variable=userv)
passv = tkinter.IntVar(winu)
passr = tkinter.Checkbutton(winu, text="New Password: ", variable=passv)

我找不到完全支持这一点的官方文档,但这里有一个 来自effbot 的 sn-p 顺便提到了这种可能性:

要创建一个 Tkinter 变量,调用相应的构造函数:

var = StringVar()

请注意,构造函数采用可选的小部件参数,但没有值参数;要设置值,请调用 set 方法:

var = StringVar() var.set("你好")

只有当你使用多个 Tk 实例运行 Tkinter 时,构造函数参数才有意义(你不应该这样做,除非你真的知道自己在做什么)。

【讨论】:

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