首页 > 解决方案 > 来自 tkinter 的小部件在我的功能中未被识别

问题描述

我正在制作一个凯撒密码 GUI,我正在努力让我的数据输入和输出在我的函数中工作。当我尝试将 .get 或 .insert 与我的文本小部件一起使用时,出现错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\sethb\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "C:/Users/sethb/PycharmProjects/TextCipher/Cipher 2.0.py", line 52, in <lambda>
    cipher = ttk.Button(self, text='Cipher', command=lambda: clickedCipher())
  File "C:/Users/sethb/PycharmProjects/TextCipher/Cipher 2.0.py", line 111, in clickedCipher
    string = inserttxt.get()
NameError: name 'inserttxt' is not defined.  

我还没有找到解决方案。如果有人知道我做错了什么,我将不胜感激。这是我需要开始工作的最后一件事。

import tkinter as tk
from tkinter import messagebox
from tkinter import ttk

class tkinterApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (mainWindow, newWindow):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(mainWindow)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

class mainWindow(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        lbl = ttk.Label(self,
                text="Welcome to my Caesar Cipher.  To begin the cipher                 
   press start.\nTo learn more about"
                        " the Caesar Cipher press facts.")
        lbl.grid(column=0, row=0)

        factsbtn = ttk.Button(self, text="Facts", command=clickedFacts)
        factsbtn.grid(row=2, column=1, padx=10, pady=10)

        startbtn = ttk.Button(self, text="Start", command=lambda:     
        controller.show_frame(newWindow))
        startbtn.grid(row=1, column=1, padx=10, pady=10)

   class newWindow(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        enterlbl = ttk.Label(self, text="Enter your text below and click 
Cipher to run the cipher program")
        enterlbl.grid(row=0)

        inserttxt = tk.Text(self)
        inserttxt.insert(tk.END, 'enter your message here')
        inserttxt.grid(row=1)

        cipher = ttk.Button(self, text='Cipher', command=lambda: 
clickedCipher())
        cipher.grid(row=2)

        outputlbl = ttk.Label(self, text="The ciphered text is:")
        outputlbl.grid(row=3)

        ntxtbox = tk.Text(self)
        ntxtbox.grid(row=4)

def clickedFacts():
    History='    The Caesar Cipher is an encryption method that dates back 
to the 1st century B.C.  It is named' \
        ' after Julias Caesar who used it to send military messages across 
his empire.  It is believed that when' \
        ' his enemies found it, they assumed the messages were written in 
another language and simply did not try' \
        ' to decipher it.\n \n    My cipher uses an 8 letter shift, 
meaning an A will be written as an I.  Julius' \
        ' Caesar is believed to have used a shift of 3, while his nephew 
used a shift of only 1'
    messagebox.showinfo('Facts', History)

def split(word):
    return [char for char in word]

def shift(indexes):

    if indexes < 25 - 8:
        indexes += 8
    else:
        indexes -= 17
    return indexes

def intoCipher(otext, p, k):
    arrLow = ['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']
    arrCap = ['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']
    indexA = 0
    lowOrUp = '0'
    b = 0
    x = len(otext)
    index = 0
    while index < x:
        while indexA < 25 and lowOrUp == '0':
            if otext[index] == arrLow[indexA]:
                lowOrUp = '1'
                p = indexA
                b = 1
            elif otext[index] == arrCap[indexA] and lowOrUp == '0':
                lowOrUp = '1'
                p = indexA
                b = 2
            indexA += 1
        k = shift(p)
        if b == 1:
            otext[index] = arrLow[k]
        elif b == 2:
            otext[index] = arrCap[k]
        b = 0
        lowOrUp = '0'
        index += 1
        indexA = 0
    return otext

def clickedCipher():
   string = global inserttxt.get()
    string = str(string)
    string = intoCipher(string, 0, 0)
    string = ''.join(string)
    global ntxtbox.insert(0, string)

app = tkinterApp()
app.mainloop()

标签: python-3.xtkinter

解决方案


inserttxt是一个局部变量。要使其成为全局变量,您必须在创建它时将其声明为全局变量。

但是,由于您使用的是类,因此最好将其设为实例变量。然后,您应该clickedCipher在该类上创建一个方法,然后该方法将可以轻松访问变量而不会污染全局命名空间。

它看起来像这样:

class newWindow(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        ...
        self.inserttxt = tk.Text(self)
        self.ntxtbox = tk.Text(self)
        cipher = ttk.Button(self, text='Cipher', command=self.clickedCipher)
        ...

    def clickedCipher(self):
        string = self.inserttxt.get()
        string = str(string)
        string = intoCipher(string, 0, 0)
        string = ''.join(string)
        self.ntxtbox.insert(0, string)

推荐阅读