Tkinter с ООП-питоном

Моя цель - получить очень простой графический интерфейс с двумя вкладками, где на первой есть параметры входа в систему, регистрации нового пользователя и отмены регистрации этого пользователя. Если я хочу нажать на второй вариант (зарегистрировать пользователя или вызвать «darse de alta»), должно появиться второе окно (и закрыть первое), где я могу указать свою информацию для регистрации (имя, dni и номер телефона) . Тогда последним пунктом этой программы должно быть добавление этого нового пользователя в базу данных с именем self.socios. Это связано с тем, что в методе «agregar» внутри класса Registro_socios всякий раз, когда я хочу зарегистрировать нового пользователя, его нужно добавить в базу данных. Я не знаю, как связать нового пользователя с ранее созданным классом. Спасибо всем, кто хоть как-то объяснит и разъяснит.

class Socio:
    
    def __init__(self,nombre_socio,dni,telefono):
        self.nombre = nombre_socio
        self.dni = dni
        self.telefono = telefono
    
    def __str__(self):
        return "Nombre: {0}\nDNI: {1}\nTelefono: {2}".format(self.nombre,self.dni,self.telefono)

class Registro_socios: 
    
    def __init__(self,baseDatos_socios = None):
        if baseDatos_socios is None:
            baseDatos_socios = {} # Diccionario vacío con DNIs como Keys
            self.socios = baseDatos_socios
    
    def agregar(self,socio):
        if self.existe(socio): # En el caso que existe retorne True
            raise KeyError(f'{socio.__class__.__name__} ya existente') # A Python KeyError exception is what is raised when you try to access a key that isn't in a dictionary ( dict )
        self.socios[socio.dni] = socio
    
    def existe(self,socio):
        if socio.dni in self.socios:
            return True
        return False

root = tk.Tk()
miFrame = Frame(root) 
# miFrame = Frame(root,width=1000,height=500) 
miFrame.pack()

def alta_socio():
    otra_ventana = tk.Toplevel(root)
    miFrame2 = Frame(otra_ventana)
    miFrame2.pack()
    
    texto_nombreUsuario = Entry(miFrame2).grid(row=0,column=1, padx=5, pady=5)
    nombre_usuario = Label(miFrame2, text='Nombre de socio: ').grid(row=0,column=0, padx=5, pady=5)

    texto_DNI = Entry(miFrame2).grid(row=1,column=1, padx=5, pady=5)
    nombre_usuario = Label(miFrame2, text='DNI: ').grid(row=1,column=0, padx=5, pady=5)

    texto_nombreUsuario = Entry(miFrame2).grid(row=2,column=1, padx=5, pady=5)
    nombre_usuario = Label(miFrame2, text='Teléfono de contacto: ').grid(row=2,column=0, padx=5, pady=5)
    
    root.iconify() 

botonInicio = Button(root, text='Entrar',bg='orange')
botonInicio.pack()

boton_AltaSocio = Button(root, text='Darse de alta',bg='orange', command=alta_socio) 
boton_AltaSocio.pack()

boton_BajaSocio = Button(root, text='Darse de baja',bg='orange', command=baja_socio)
boton_BajaSocio.pack()

root.mainloop()

Для ваших кнопок внизу я вижу command=function и command=baja_socio, но я не вижу какой-либо определенной функции с именем function или baja_socio, поэтому я не вижу, как python не остановится на этом и не пожалуется, если вы не определили их вне того, что вы показываете.

Andrew Allaire 11.12.2020 20:39

вау, такую ​​ошибку я сделал, я исправляю это сейчас. И первая проблема не появления второго окна устранена.

Alex Garcia 11.12.2020 20:52

Ну, я все еще не вижу функции baja_socio. В функции alto_socio я не совсем уверен, каково ваше намерение, но вместо того, чтобы создавать новые объекты виджетов Entry в обратном вызове, я бы рекомендовал, чтобы виджеты Entry уже были созданы, когда вы запускаете свое приложение, все упаковано во фрейм. Затем просто упакуйте и распакуйте свои обратные вызовы нужных вам кадров. Я считаю, что это проще всего, когда ваши обратные вызовы являются методами, и вы сохраняете виджеты как атрибуты экземпляра, на которые могут ссылаться методы.

Andrew Allaire 11.12.2020 21:20
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
139
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я вижу здесь много ошибок. Во-первых, вы вызываете главное окно с помощью tk.Tk(), а кадры — с помощью Frame, поэтому я предполагаю, что вы дважды импортируете tkinter следующим образом:

import tkinter as tk
from tkinter import *

Забудьте о втором импорте и поставьте tk перед каждым виджетом.

Затем кнопка «dar-se baja» вызывает метод, который не определен.

Внутри метода alta_socio вы делаете это:

texto_nombreUsuario = tk.Entry(miFrame2).grid(row=0,column=1, padx=5, pady=5)

Это плохо, потому что, хотя tk.Entry() возвращает экземпляр класса Entry, метод Entry.grid() ничего не возвращает. поэтому texto_nombeUsuario будет None, и вы не сможете получить доступ к тому, что находится в виджете входа. Вместо этого вы должны сделать следующее:

texto_nombreUsuario = tk.Entry(miFrame2)
texto_nombreUsuario.grid(row=0,column=1, padx=5, pady=5)

Другой вариант - использовать StringVar:

texto_nombreUsuario = tk.StringVar(root)
tk.Entry(miFrame2, textvariable=texto_nombreUsuario).grid(row=0,column=1, padx=5, pady=5)

Для третьей записи в alta_socio() вы используете для телефона ту же переменную, что и для имени. Почини это. Наконец, вы можете добавить tk.Button, который будет вызывать метод, создающий Socio. Нравиться:

tk.Button(miFrame2, text='Confirmar', command=add_socio).grid()

Метод add_socio() может быть вложенным методом из alta_socio(), таким образом, он будет иметь доступ к переменным texto_nombreUsuario, texto_DNI и texto_telefono. Он получает текст из texto_nombreUsuario с помощью команды texto_nombreUsuario.get() и вызывает ранее созданные классы:

def alta_socio():
    def add_socio(): # this function is nested so it can access variables defined in alta_socio
        nombre = texto_nombreUsuario.get()
        tel = texto_telefono.get()
        dni = texto_dni.get()
        socio = Socio(nombre, dni, telefono) # here you call the Socio class previously defined

    otra_ventana = tk.Toplevel(root)
    miFrame2 = tk.Frame(otra_ventana)
    miFrame2.pack()
    
    texto_nombreUsuario = tk.StringVar(root) # this is a tkinter variable which contains the user name
    # this entry saves it values in the tkinter variable above:
    tk.Entry(miFrame2, textvariable=texto_nombreUsuario).grid(row=0,column=1, padx=5, pady=5)
    tk.Label(miFrame2, text='Nombre de socio: ').grid(row=0,column=0, padx=5, pady=5)
    ...

Спасибо за все, но я все еще не вижу последнего замечания, которое вы сделали о вложенном методе. У меня есть метод под названием «агрегар», но он ждет аргумента, с которым будет работать социо, а у социо есть номер телефона, дни и имя. Так что я немного растерялся, когда вы предложили использовать команду get to only texto_nombreUsuario, поскольку это не единственная вещь, определяющая социо. Если бы вы могли объяснить немного больше, я был бы признателен за это заранее.

Alex Garcia 11.12.2020 22:10

@AlexGarcia Я добавил пример в конце своего ответа, чтобы вы могли увидеть, как создать вложенную функцию. Идея состоит в том, что если вы определили новую функцию внутри alta_socio, она может получить доступ к локальным переменным в ней, поэтому вам не нужно передавать имя или телефон в качестве аргумента функции.

Flavio Moraes 12.12.2020 04:15

Другие вопросы по теме