I'm trying to build my first app using python and tkinter. I'm stuck where I can't run the content from another class into the same first window.
The first window is a login window, here is the full code of the class:
import tkinter as tk
import sqlite3
from tkinter import *
from gamecontent import Gamecontent
class MainApp(Tk):
def __init__(self):
Tk.__init__(self)
self.title('Word Warrior - Sign In')
self.geometry("650x510")
self.resizable(width=False, height=False)
# Create widgets
self.label_username = tk.Label(self, text="Username")
self.label_password = tk.Label(self, text="Password")
self.entry_username = tk.Entry(self)
self.entry_password = tk.Entry(self, show="*")
self.button_login = tk.Button(self, text="Login", command=self.login)
self.button_createacc = tk.Button(self, text="Create Account", command=self.createacc)
# Place widgets
self.label_username.place(x=200, y=150)
self.label_password.place(x=200, y=200)
self.entry_username.place(x=280, y=152, width=140, height=27)
self.entry_password.place(x=280, y=202, width=140, height=27)
self.button_login.place(x=280, y=242, width=140, height=27)
self.button_createacc.place(x=280, y=282, width=140, height=27)
# Create database and tables and cursor object
self.conn = sqlite3.connect('users.db')
self.c = self.conn.cursor()
self.c.execute("CREATE TABLE IF NOT EXISTS users (username text UNIQUE, password text)")
self.conn.commit()
self.conn.close()
def clear_content(self):
for widget in self.winfo_children():
widget.destroy()
def login(self):
# Get the username and password from the entry widgets
username = self.entry_username.get()
password = self.entry_password.get()
# Fetch username and password from the database
conn = sqlite3.connect('users.db')
c = conn.cursor()
c.execute("SELECT * FROM users WHERE username=? AND password=?", (username, password))
result = c.fetchone()
conn.close()
# Check if the username and password are correct
if result:
# If the login is successful, open a new window with the flashcard game
self.clear_content()
Gamecontent()
else:
# If the login is not successful, display an error message
self.label_message = tk.Label(self, text=" Wrong credentials ")
self.label_message.place(x=285, y=322)
def createacc(self):
# Get the username and password from the entry widgets
username = self.entry_username.get()
password = self.entry_password.get()
# Checks if user is entering an empty username/password while creating
if username == "" or password == "":
self.label_message = tk.Label(self, text=" Can't be empty ")
self.label_message.place(x=290, y=322)
else:
# Connect to the database (or create it if it doesn't exist)
conn = sqlite3.connect('users.db')
c = conn.cursor()
# Create the table if it doesn't exist
c.execute('''CREATE TABLE IF NOT EXISTS users
(username text, password text)''')
# Checks if an account with the same username exists
c.execute("SELECT * FROM users WHERE username = ?", (username,))
if c.fetchone() is None:
c.execute("INSERT INTO users VALUES (?, ?)", (username, password))
conn.commit()
self.label_message = tk.Label(self, text=" Account created ")
self.label_message.place(x=290, y=322)
else:
self.label_message = tk.Label(self, text=" Username exists ")
self.label_message.place(x=290, y=322)
# Close the connection
conn.close()
app = MainApp()
app.mainloop()
The change must be done when the login is correct, exactly in
self.clear_content()
Gamecontent()
The problem is that Gamecontent opens in another window and not into the same window.
Here is the code for Gamecontent class
from tkinter import *
from random import randint
from gamedata import words, count
class Gamecontent(Tk):
def __init__(self):
Tk.__init__(self)
self.title('Word Warrior - Play')
self.geometry("650x510")
self.resizable(width=False, height=False)
def next():
global hinter, hinter_count
# Clear the screen
answer_label.config(text="")
my_entry.delete(0, END)
hint_label.config(text="")
# Reset Hint stuff
hinter = ""
hinter_count = 0
# Create random selection
global random_word
random_word = randint(0, count-1)
# update label with Spanish Word
spanish_word.config(text=words[random_word][0])
def answer():
if my_entry.get().capitalize() == words[random_word][1]:
answer_label.config(text=f"Correct! {words[random_word][0]} is {words[random_word][1]}")
else:
answer_label.config(text=f"Incorrect! {words[random_word][0]} is not {my_entry.get().capitalize()}")
def hint():
global hinter_count
global hinter
if hinter_count < len(words[random_word][1]):
hinter = hinter words[random_word][1][hinter_count]
hint_label.config(text=hinter)
hinter_count =1
# Labels
spanish_word = Label(self, text="", font=("Helvetica", 36))
spanish_word.pack(pady=50)
answer_label = Label(self, text="")
answer_label.pack(pady=20)
my_entry = Entry(self, font=("Helvetica", 18))
my_entry.pack(pady=20)
# Create Buttons
button_frame = Frame(self)
button_frame.pack(pady=20)
answer_button = Button(button_frame, text="Answer", command=answer)
answer_button.grid(row=0, column=0, padx=20)
next_button = Button(button_frame, text="Next", command=next)
next_button.grid(row=0, column=1)
hint_button = Button(button_frame, text="Hint", command=hint)
hint_button.grid(row=0, column=2, padx=20)
# Create Hint Label
hint_label = Label(self, text="")
hint_label.pack(pady=15)
# Run next function when program starts
next()
self.mainloop()
I'm stuck with this for a while and can't move forward, I'm not even sure it's possible with tkinter to do so.
I tried clearing the content of the window and start an instance of the second class but it opens in another window.
CodePudding user response:
Change
self.clear_content()
Gamecontent()
to
self.clear_content()
Gamecontent(self)
In gamecontent itself change
class Gamecontent(Tk):
def __init__(self):
Tk.__init__(self)
self.title('Word Warrior - Play')
self.geometry("650x510")
self.resizable(width=False, height=False)
to
class Gamecontent(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
#self.config(bg="white")
self.pack(fill=BOTH, expand=True)
parent.title('Word Warrior - Play')
This makes gamecontent to a frame which packs itself into your main app