Пользовательский ввод из графического интерфейса в Python 3.5

Итак, я новичок в Python, но у меня возникают проблемы с обработкой переменных после их помещения в класс.

Следующий код отлично работает, когда нет окружающего класса, но как только я добавляю его, я получаю сообщение об ошибке:

NameError: name 'someName' is not defined

Что происходит на 3-й строке

text = "You have entered " + someName.get()

Вот код:

class GUI:
    def changeLabel():
        text = "You have entered " + someName.get()
        labelText.set(text)
        someName.delete(0, END)
        someName.insert(0, "You've clicked!")
        return

    app = Tk()
    app.title("GUI Test")
    app.geometry('450x300')

    labelText = StringVar()
    labelText.set("Click when ready")
    label1 = Label(app, textvariable=labelText, height=4)
    label1.pack()

    userInput = StringVar(None)
    someName = Entry(app, textvariable=userInput)
    someName.pack()

    button1 = Button(app, text="Click Here", width=20,command=changeLabel)
    button1.pack(side='bottom',padx=15,pady=15)

    app.mainloop()

GUI #calling the class to run

Любая помощь будет принята с благодарностью.


person coelicasi    schedule 15.01.2016    source источник
comment
GUI #calling the class to run Нет. Это не то, как вы это называете. Пожалуйста, сначала ознакомьтесь с учебниками по классам python.   -  person Lafexlos    schedule 15.01.2016
comment
Здесь много проблем. Вероятно, вам следует перечитать учебник TKinter.   -  person Morgan Thrapp    schedule 15.01.2016
comment
Кроме того, вы должны описать в своем вопросе, что вы ожидаете от своего кода.   -  person PM 2Ring    schedule 15.01.2016


Ответы (2)


Ваш класс GUI сформирован неправильно. Вы не должны просто сбрасывать код в класс, он должен быть в методе (функции, принадлежащей классу). Для подобных вещей обычный способ сделать это — поместить его в метод __init__, который вызывается автоматически, когда вы создаете экземпляр класса, вызывая его.

Методы могут иметь свои собственные локальные переменные, и они также могут обращаться к атрибутам экземпляра, используя синтаксис self.attribute_name. Ваше сообщение об ошибке NameError: name 'someName' is not defined связано с тем, что Python считает, что someName является локальной переменной changeLabel, но не понимает, что это должен быть ваш виджет Entry.

Во всяком случае, я исправил ваш код, чтобы он работал; предположительно, он делает то, что вы намеревались. Обратите внимание, что методы имеют self в качестве первого аргумента. Пожалуйста, прочтите некоторые документы/учебники Python о классах для получения дополнительной информации.

from Tkinter import *

class GUI(object):
    def changeLabel(self):
        text = "You have entered " + self.someName.get()
        self.labelText.set(text)
        self.someName.delete(0, END)
        self.someName.insert(0, "You've clicked!")            

    def __init__(self):
        app = Tk()
        app.title("GUI Test")
        app.geometry('450x300')

        self.labelText = StringVar()
        self.labelText.set("Click when ready")
        label1 = Label(app, textvariable=self.labelText, height=4)
        label1.pack()

        userInput = StringVar(None)
        self.someName = Entry(app, textvariable=userInput)
        self.someName.pack()

        button1 = Button(app, text="Click Here", width=20,command=self.changeLabel)
        button1.pack(side='bottom',padx=15,pady=15)

        app.mainloop()

GUI() #calling the class to run

Этот код работает на Python 2; вам нужно изменить оператор import в Python 3 на from tkinter import *. На самом деле не рекомендуется использовать import *, так как он загрязняет ваше пространство имен всеми импортируемыми именами. Лучше сделать что-то вроде

import tkinter as tk

а затем напишите свои ссылки Tkinter, например

app = tk.Tk()

а также

label1 = tk.Label(app, textvariable=self.labelText, height=4)

Так далее

person PM 2Ring    schedule 15.01.2016
comment
Спасибо. Я знаю, что это далеко не приличный код Python, и учебные пособия, которые я изучал, не включали классы и методы, настроенные так, как вы указали выше. Я полагаю, что мне придется как можно быстрее просмотреть несколько хороших руководств. - person coelicasi; 18.01.2016
comment
@coelicasi: Нет проблем. Шаблон import * довольно часто встречается в примерах кода (даже в официальных документах/учебниках), поскольку он делает код менее подробным, но, к сожалению, дает людям представление о том, что это хорошая практика. Вы можете делать простые вещи с графическим интерфейсом, не организуя свой код в класс, но это быстро приводит к путанице, когда вы пытаетесь создать сложный графический интерфейс. Помимо просмотра учебных пособий, прямо здесь, на SO, есть много отличных примеров кода, хотя иногда даже эксперты будут использовать шаблон import * для простоты. - person PM 2Ring; 18.01.2016

У вас есть ошибки в коде, и вы не используете классы должным образом. Я изменил ваш код и прокомментировал новые строки, чтобы вы поняли, что происходит. Я добавил self ссылок ко всем текстовым переменным, чтобы к ним можно было правильно обращаться.

from tkinter import *

class GUI:
        #set these so that they are able to be used by the whole class
        labelText = ""
        userInput = "" 

        #you should have an init method for your classes and do all the setup here
        def __init__(self,master):   
                self.labelText = StringVar()
                self.userInput = StringVar()

                #you should pack things into a frame
                frame = Frame(master)     
                frame.pack()

                self.labelText.set("Click when ready")
                label1 = Label(frame, textvariable=self.labelText, height=4)
                label1.pack()

                someName = Entry(frame, textvariable=self.userInput)
                someName.pack()

                button1 = Button(frame, text="Click Here", width=20,command=self.changeLabel)
                button1.pack(side='bottom',padx=15,pady=15)

        def changeLabel(self):
                text = "You have entered " + self.userInput.get()
                self.labelText.set(text)
                self.userInput.set("You've clicked!")
                return

#create the app before you call the GUI.
app = Tk()
app.title("GUI Test")
app.geometry('450x300')

# when you create the class, you need to assign it to a variable
applet = GUI(app) #calling the class to run
app.mainloop()
person Brandon Deo    schedule 15.01.2016