Score board from database with tkinter and SQLite - python-3.x

I've been adding a little extra functionality to a sample snake game which I downloaded from git hub but have hit a bit of a brick wall with regard to the score board. At the moment the extras I've added are:
A username entry and validation at the start of the game
Username displayed as the game is playing
Username and score are written to a database at the end of the game
A leaderboard is displayed at the end of the game
At the moment my leaderboard only pulls the data from the database and displays it in a label. Ideally I want it to read all of the data into some kind of data structure and only display the top 15 scores after a sort is performed on the records. Is there a relatively simple way to achieve this at all?
Here is my code so far:
import sqlite3
import tkinter as tk
from random import randint
from PIL import Image, ImageTk
from tkinter import messagebox, END
from sqlalchemy import create_engine
MOVE_INCREMENT = 20
MOVES_PER_SECOND = 15
GAME_SPEED = 1000 // MOVES_PER_SECOND
class Snake(tk.Canvas):
def __init__(self, parent, username):
self.username = username
super().__init__(
parent, width=600, height=620, background="black", highlightthickness=0
)
# Rest of the Snake class code goes here
self.snake_positions = [(100, 100), (80, 100), (60, 100)]
self.food_position = self.set_new_food_position()
self.direction = "Right"
self.score = 0
self.load_assets()
self.create_objects()
self.bind_all("<Key>", self.on_key_press)
self.pack()
self.after(GAME_SPEED, self.perform_actions)
def load_assets(self):
try:
self.snake_body_image = Image.open("./assets/snake.png")
self.snake_body = ImageTk.PhotoImage(self.snake_body_image)
self.food_image = Image.open("./assets/food.png")
self.food = ImageTk.PhotoImage(self.food_image)
except IOError as error:
print(error)
root.destroy()
def create_objects(self):
self.create_text(45, 12, text=f"Score: {self.score}", tag="score", fill="#fff", font=(10))
self.create_text(490, 12, text=f"Username: {self.username}", tag="username", fill="#fff", font=(10))
for x_position, y_position in self.snake_positions:
self.create_image(
x_position, y_position, image=self.snake_body, tag="snake"
)
self.create_image(*self.food_position, image=self.food, tag="food")
self.create_rectangle(7, 27, 593, 613, outline="#525d69")
def check_collisions(self):
head_x_position, head_y_position = self.snake_positions[0]
return (
head_x_position in (0, 600)
or head_y_position in (20, 620)
or (head_x_position, head_y_position) in self.snake_positions[1:]
)
def check_food_collision(self):
if self.snake_positions[0] == self.food_position:
self.score += 1
self.snake_positions.append(self.snake_positions[-1])
self.create_image(
*self.snake_positions[-1], image=self.snake_body, tag="snake"
)
self.food_position = self.set_new_food_position()
self.coords(self.find_withtag("food"), *self.food_position)
score = self.find_withtag("score")
self.itemconfigure(score, text=f"Score: {self.score}", tag="score")
def end_game(self):
self.delete(tk.ALL)
self.create_text(
self.winfo_width() / 2,
self.winfo_height() / 2,
text=f"Game over! You scored {self.score}!",
fill="#fff",
font=("", 8)
)
def write_to_database(self):
try:
# Open the Score Database
connection = sqlite3.connect("ScoreDatabase.db")
cursor = connection.cursor()
UserRec = []
UserRec.append(self.username)
UserRec.append(self.score)
# SQL statement to insert the user record into the Gamers table
buffer = "INSERT INTO Gamers VALUES (?, ?)"
cursor.execute(buffer, (self.username, self.score))
connection.commit()
connection.close()
except sqlite3.Error as e:
print("An error occurred:", e.args[0])
connection.close()
# End of new database code
def show_database_entries(self):
try:
con = sqlite3.connect("ScoreDatabase.db")
cur = con.cursor()
# Show all rows in the database
buffer = "SELECT * FROM Gamers;"
buffer = buffer.strip()
cur.execute(buffer)
rows = cur.fetchall()
count = 0
print()
print("Database entries -Username Score")
for x in rows:
print(str(x[0]) + ": " + str(x[1]))
count += 1
print()
con.commit()
con.close()
except sqlite3.Error as e:
print("An error occurred:", e.args[0])
connection.close()
def move_snake(self):
head_x_position, head_y_position = self.snake_positions[0]
if self.direction == "Left":
new_head_position = (head_x_position - MOVE_INCREMENT, head_y_position)
elif self.direction == "Right":
new_head_position = (head_x_position + MOVE_INCREMENT, head_y_position)
elif self.direction == "Down":
new_head_position = (head_x_position, head_y_position + MOVE_INCREMENT)
elif self.direction == "Up":
new_head_position = (head_x_position, head_y_position - MOVE_INCREMENT)
self.snake_positions = [new_head_position] + self.snake_positions[:-1]
for segment, position in zip(self.find_withtag("snake"), self.snake_positions):
self.coords(segment, position)
def on_key_press(self, e):
new_direction = e.keysym
all_directions = ("Up", "Down", "Left", "Right")
opposites = ({"Up", "Down"}, {"Left", "Right"})
if (
new_direction in all_directions
and {new_direction, self.direction} not in opposites
):
self.direction = new_direction
def perform_actions(self):
if self.check_collisions():
self.end_game()
self.write_to_database()
show_leaderboard()
self.check_food_collision()
self.move_snake()
self.after(GAME_SPEED, self.perform_actions)
def set_new_food_position(self):
while True:
x_position = randint(1, 29) * MOVE_INCREMENT
y_position = randint(3, 30) * MOVE_INCREMENT
food_position = (x_position, y_position)
if food_position not in self.snake_positions:
return food_position
root = tk.Tk()
root.title("Snake")
root.withdraw() # Hide root window for now
def StartGame():
username = UsernInput.get()
if len(username) > 8:
messagebox.showwarning("Invalid username", "Please enter a username of 8 characters or less")
window.focus()
else:
window.destroy() # Get rid of the username input
root.deiconify() # Show the root window again
root.tk.call("tk", "scaling", 4.0)
root.resizable(False, False)
board = Snake(root, username)
return username
def show_leaderboard():
leaderboard = tk.Toplevel()
leaderboard.focus
leaderboard.title("Leaderboard")
leaderboard.geometry('400x500')
leaderboard['bg'] = 'black'
leaderboard.tk.call("tk", "scaling", 4.0)
leaderboard.resizable(False, False)
Usern_label = tk.Label(leaderboard, text="High Scores", font=("Arial Bold", 12))
Usern_label.place(x=10, y=15)
Usern_label.config(fg="yellow")
Usern_label.config(bg="black")
my_con = sqlite3.connect('ScoreDatabase.db')
cursor = my_con.cursor()
cursor.execute("SELECT *, oid FROM Gamers LIMIT 15")
data = cursor.fetchall()
showData = ''
for data in data:
showData = showData.replace("'", "")
showData = showData.replace(",", "")
showData = showData.replace("(", "")
showData = showData.replace(")", "")
showData += str(data) + "\n"
results = tk.Label(leaderboard, text=showData, justify='left', width=15, font=("Arial", 6))
results.place(x=0, y=85)
results.config(fg="white")
results.config(bg="black")
my_con.commit()
my_con.close()
# New database code
#Create or open the Score Database * This works fine
connection = sqlite3.connect("ScoreDatabase.db")
cursor = connection.cursor()
# SQL statement to create the table structure of the Scoredatabase
try:
# following code runs once to create a new database named above
buffer ="CREATE TABLE IF NOT EXISTS Gamers (Username, Score, primary key(Username));"
buffer = buffer.strip()
cursor.execute(buffer)
connection.commit()
except sqlite3.Error as e:
print("An error occurred:", e.args[0])
connection.close()
# End of new database code
window = tk.Toplevel()
window.title("Snake game")
window.geometry('300x175')
window['bg']='black'
Instructions_label = tk.Label(window, bg='black', text="Enter your username to be entered into the score database. Usernames must be 8 characters or less ", wraplength=300, justify='left', font=("Arial Bold", 12))
Instructions_label.place(x=10, y=10)
Instructions_label.config(fg="#FFFFFF")
Instructions_label.config(bg="black")
Usern_label= tk.Label(window, bg='black', text="Username: ", font=("Arial Bold", 12))
Usern_label.place(x=10, y=90)
Usern_label.config(fg="#FFFFFF")
Usern_label.config(bg="black")
UsernInput = tk.Entry(window, bg='White', bd=1, width=20, highlightthickness=2)
UsernInput.place(x=110, y=90)
UsernInput.config(highlightbackground = "yellow", highlightcolor= "yellow")
usern_button = tk.Button(window, text='Start Game', bd='3', command=StartGame)
usern_button.place(x=20, y=130)
root.mainloop()

Related

PyQt 6. Progress bar freezes mainwindow

I am writing program with PyQT6 lib.
In program I have some big calculations (class in 2nd .py file), which take some time. I implemented progress bar and now I am trying to prevent freeze of Gui. I find what I need to use threads and signals to communicate with bar. But it doesn't work, as i can see. Program behavior isn't clear for me because on Linux Ubuntu 18 this program works fine with out freeze.
Can smb help me? What am I doing wrong?
here code example:
mainWindow.py
`
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.resize(800, 150)
self.n_times_clicked = 0
self.setWindowTitle("Выгрузка отчета риска")
self.button = QPushButton("Загрузить файл типа 'Scens'")
self.button.clicked.connect(self.the_button_was_clicked)
self.button.adjustSize()
self.button1 = QPushButton("Загрузить файл типа 'Зоны'")
self.button1.clicked.connect(self.the_button_was_clicked_second)
self.button1.adjustSize()
self.button2 = QPushButton("Переформатировать и выгрузить")
self.button2.clicked.connect(self.btn2_was_clicked)
self.button2.adjustSize()
self.button3 = QPushButton("Переформатировать и выгрузить")
self.button3.clicked.connect(self.btn3_was_clicked)
self.button3.adjustSize()
self.progressbar = QProgressBar()
self.progressbar.setValue(0)
self.input1 = QLineEdit("")
self.input1.setPlaceholderText("Введите путь до файла: C:\\user\\file.docx")
self.input2 = QLineEdit("")
self.input2.setPlaceholderText("Введите путь до файла: C:\\user\\file.docx")
layout = QGridLayout()
layout.addWidget(self.button, 0, 0)
layout.addWidget(self.input1, 0, 1)
layout.addWidget(self.button2, 0, 2)
layout.addWidget(self.button1, 1, 0)
layout.addWidget(self.input2, 1, 1)
layout.addWidget(self.button3, 1, 2)
layout.addWidget(self.progressbar, 2, 0, 2, 3)
self.progressbar.setHidden(True)
layout.setRowStretch(2, 1)
container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
def the_button_was_clicked_second(self):
#some code
return fname
def the_button_was_clicked(self):
#some code
return fname
def btn2_was_clicked(self):
self.button2.setEnabled(False)
if get_file_extension(self.input1.text()) == 0:
if Path(self.input1.text()).exists():
self.progressbar.setHidden(False)
saveFile = QFileDialog.getSaveFileName(self, 'Save File', "Новый отчет.docx", "Word файл (*.docx)")
if saveFile[0] != "":
input_data = self.input1.text()
check = 0
check = worker.edit_excel(input_data, saveFile[0])
self.input1.clear()
if check == 1:
msg = QMessageBox()
msg.setWindowTitle("Ошибка")
msg.setText("Структура выбраного файла не соответсвует структуре 'Scens'.")
msg.setIcon(QMessageBox.Icon.Critical)
a = msg.exec()
else:
msg = QMessageBox()
msg.setWindowTitle("Готово!")
msg.setText("Word файл успешно создан")
msg.setIcon(QMessageBox.Icon.Information)
a = msg.exec()
self.progressbar.setValue(0)
self.button2.setEnabled(True)
self.progressbar.setHidden(True)
else:
print("no file selected")
else:
msg = QMessageBox()
msg.setWindowTitle("Ошибка")
msg.setText("Вы выбрали несуществующий файл")
msg.setIcon(QMessageBox.Icon.Critical)
a = msg.exec()
else:
msg = QMessageBox()
msg.setWindowTitle("Ошибка")
msg.setText("Вы выбрали файл неверного расширения. Допустимые файлы *.xls и *.xlsx")
msg.setIcon(QMessageBox.Icon.Critical)
a = msg.exec()
self.input1.clear()
def btn3_was_clicked(self):
#some code
def signal_accept(self, msg):
if int(msg) > 100:
self.progressbar.setValue(100)
else:
self.progressbar.setValue(int(msg))
if self.progressbar.value() == 100:
# self.progressbar.setValue(0)
self.button2.setEnabled(True)
app = QApplication(sys.argv)
window = MainWindow()
worker = Excel_redactor.Excel()
worker._signal.connect(window.signal_accept)
worker.start()
window.show()
sys.exit(app.exec())
`
and in second file I have calculations:
`
class Excel(QThread):
_signal = pyqtSignal(int)
def __init__(self):
super(Excel, self).__init__()
def __del__(self):
self.wait()
def another_e(self, chislo):
power = int(str(chislo)[-2] + str(chislo)[-1])
value_new = float(str(chislo * pow(10, power))[:-2])
return value_new
def sort_dict(self, dict):
dictionary_keys = list(dict.keys())
sorted_dict = {dictionary_keys[x]: sorted(
dict.values())[x] for x in range(len(dictionary_keys))}
return sorted_dict
def edit_excel(self, excel_path, word_path):
#some code
j = 0
step = all_rows / 100
percent = 1
for row in range(2, all_rows-2):
if row % step < 1.0 and row % step >= 0.0:
percent += 1
self._signal.emit(percent)
#some code
return 0
`
I tried to move QThread .start inside btn2_was_clicked func, but in that case gui doesnt work if i do "huge calculations" more than 1 time

Game with username entry using tkinter

I've downloaded a sample snake game from this github and I am desperately trying to modify the code to have an additional username entry window which then displays the username as the game is being played. I'd also hoping to code a leaderboard once I have the current issue sorted out.
My problem is that while the game itself works great as soon as I added the additional code to open the username entry window at the start the window dimension are applied to the game window as well.
Can anyone point out the likely blindingly obvious thing I'm missing here? My code is everything after the comment line.
import tkinter as tk
from random import randint
from PIL import Image, ImageTk
from tkinter import messagebox
MOVE_INCREMENT = 20
MOVES_PER_SECOND = 15
GAME_SPEED = 1000 // MOVES_PER_SECOND
def StartGame():
class Snake(tk.Canvas):
def __init__(self):
super().__init__(
width=600, height=620, background="black", highlightthickness=0
)
self.snake_positions = [(100, 100), (80, 100), (60, 100)]
self.food_position = self.set_new_food_position()
self.direction = "Right"
self.score = 0
self.load_assets()
self.create_objects()
self.bind_all("<Key>", self.on_key_press)
self.pack()
self.after(GAME_SPEED, self.perform_actions)
def load_assets(self):
try:
self.snake_body_image = Image.open("./assets/snake.png")
self.snake_body = ImageTk.PhotoImage(self.snake_body_image)
self.food_image = Image.open("./assets/food.png")
self.food = ImageTk.PhotoImage(self.food_image)
except IOError as error:
print(error)
root.destroy()
def create_objects(self):
self.create_text(
45, 12, text=f"Score: {self.score}", tag="score", fill="#fff", font=(10)
)
self.create_text(
150, 12, text=f"Username: {username}", tag="username", fill="#fff", font=(10)
)
for x_position, y_position in self.snake_positions:
self.create_image(
x_position, y_position, image=self.snake_body, tag="snake"
)
self.create_image(*self.food_position, image=self.food, tag="food")
self.create_rectangle(7, 27, 593, 613, outline="#525d69")
def check_collisions(self):
head_x_position, head_y_position = self.snake_positions[0]
return (
head_x_position in (0, 600)
or head_y_position in (20, 620)
or (head_x_position, head_y_position) in self.snake_positions[1:]
)
def check_food_collision(self):
if self.snake_positions[0] == self.food_position:
self.score += 1
self.snake_positions.append(self.snake_positions[-1])
self.create_image(
*self.snake_positions[-1], image=self.snake_body, tag="snake"
)
self.food_position = self.set_new_food_position()
self.coords(self.find_withtag("food"), *self.food_position)
score = self.find_withtag("score")
self.itemconfigure(score, text=f"Score: {self.score}", tag="score")
def end_game(self):
self.delete(tk.ALL)
self.create_text(
self.winfo_width() / 2,
self.winfo_height() / 2,
text=f"Game over! You scored {self.score}!",
fill="#fff",
font=("", 10)
)
def move_snake(self):
head_x_position, head_y_position = self.snake_positions[0]
if self.direction == "Left":
new_head_position = (head_x_position - MOVE_INCREMENT, head_y_position)
elif self.direction == "Right":
new_head_position = (head_x_position + MOVE_INCREMENT, head_y_position)
elif self.direction == "Down":
new_head_position = (head_x_position, head_y_position + MOVE_INCREMENT)
elif self.direction == "Up":
new_head_position = (head_x_position, head_y_position - MOVE_INCREMENT)
self.snake_positions = [new_head_position] + self.snake_positions[:-1]
for segment, position in zip(self.find_withtag("snake"), self.snake_positions):
self.coords(segment, position)
def on_key_press(self, e):
new_direction = e.keysym
all_directions = ("Up", "Down", "Left", "Right")
opposites = ({"Up", "Down"}, {"Left", "Right"})
if (
new_direction in all_directions
and {new_direction, self.direction} not in opposites
):
self.direction = new_direction
def perform_actions(self):
if self.check_collisions():
self.end_game()
self.check_food_collision()
self.move_snake()
self.after(GAME_SPEED, self.perform_actions)
def set_new_food_position(self):
while True:
x_position = randint(1, 29) * MOVE_INCREMENT
y_position = randint(3, 30) * MOVE_INCREMENT
food_position = (x_position, y_position)
if food_position not in self.snake_positions:
return food_position
root = tk.Tk()
root.title("Snake")
root.resizable(False, False)
root.tk.call("tk", "scaling", 4.0)
board = Snake()
root.mainloop()
# My code
window = tk.Tk()
window.title("Snake game")
window.geometry('250x120')
Usern_label= tk.Label(window, text="Username: ", font=("Arial Bold", 10))
Usern_label.place(x=10, y=10)
UsernInput = tk.Text(window, bg='White', bd=5, width=15, height=1)
UsernInput.pack
UsernInput.place(x=90, y=10)
username = UsernInput.get("1.0", "end-1c")
if len(username) > 8:
messagebox.showwarning("Invalid username", "Please enter a valid username")
usern_button = tk.Button(window, text='Start Game', bd='5', command=StartGame)
usern_button.place(x=20, y=75)
window.mainloop()
The cause of your problems is just copying the snake code and putting it in a function. You should take the Snake class out of the function. You should only have one instance of Tk, the root window. Therefore this needs to be created first. I've used .withdraw() to hide it until we need it. Then I've used Toplevel to create another window. This is like Tk but doesn't cause problems. Your current user validation does not work as you get and check the value of UsernInput immediately after creating it. Therefore it will always pass as the length of an empty string is less than 8. Instead you need to do the validation in the StartGame function. I've replaced the Text with an Entry because whilst Text would work fine, Entry is much more well suited to what you need (a single line of text).
When the user presses the button it calls StartGame. This validates the input and if it's valid it destroys the username window and shows the root, then does the same setup stuff as before. Although it isn't necessary in this case it's always a good idea to pass a parent widget to every child. In this case the snake canvas will automatically go to the root window but in your original code this is what caused the window size to be wrong as it automatically went in the username window. I've done this by adding the parent parameter to Snake and passing root. Assuming the Snake code all works fine this code should all work. If you want to use the value of username in Snake then you'll want to pass it as a parameter by changing it to def __init__(self, parent, username):. Then after adding something like self.username = username you can use it anywhere in the class.
import tkinter as tk
from random import randint
from PIL import Image, ImageTk
from tkinter import messagebox
MOVE_INCREMENT = 20
MOVES_PER_SECOND = 15
GAME_SPEED = 1000 // MOVES_PER_SECOND
class Snake(tk.Canvas):
def __init__(self, parent):
super().__init__(
parent, width=600, height=620, background="black", highlightthickness=0
)
# Rest of the Snake class code goes here
root = tk.Tk()
root.title("Snake")
root.withdraw() # Hide root window for now
def StartGame():
# Do the validation after the user has pressed the button
# The input has no value if you call it immediately after
username = UsernInput.get() # The get is easier with an Entry
if len(username) > 8:
messagebox.showwarning("Invalid username", "Please enter a valid username")
window.focus() # Go back to the window after showing the warning
else:
window.destroy() # Get rid of the username input
root.deiconify() # Show the root window again
root.tk.call("tk", "scaling", 4.0)
root.resizable(False, False)
board = Snake(root)
window = tk.Toplevel() # Don't use multiple Tk instances
window.title("Snake game")
window.geometry('250x120')
Usern_label= tk.Label(window, text="Username: ", font=("Arial Bold", 10))
Usern_label.place(x=10, y=10)
# It makes more sense to use an entry for what you are doing
UsernInput = tk.Entry(window, bg='White', bd=5, width=15)
UsernInput.place(x=90, y=10)
usern_button = tk.Button(window, text='Start Game', bd='5', command=StartGame)
usern_button.place(x=20, y=75)
root.mainloop()

How can i validate in python if a username and password already exist in mySQL Database?

Hi so I've been working on this project about a day now(New to python and mySQL)
So my question is how i can see if the input user credentials in the textbox is already a registered user?
So far I've managed to connect it to the database and store some values inside the database but i cant seem to figure out how i can scan that database and see if the user info are valid when the login button is pressed.
from tkinter import*
from tkinter import messagebox
import mysql.connector
import time
import datetime
import random
w = 300
h = 2
def register_user():
global username_info
global password_info
if len(username.get()) == 0 and len(password.get()) == 0:
print("Please fill in the Missing Info")
if len(username.get()) == 0 and len(password.get()) != 0 :
print("Please Enter a Username")
elif len(username.get()) != 0 and len(password.get()) == 0:
print("Please enter a Password")
else:
username_info = username.get()
password_info = password.get()
mydb = mysql.connector.connect(
host="localhost",
user="root",
passwd="root",
database="loginsystem"
)
mycursor = mydb.cursor()
sqlFormula = "INSERT INTO users (Username, Password) VALUES (%s, %s)"
insertvar = (username_info, password_info)
user1 = ("Joshua", "Cuyugan")
mycursor.execute(sqlFormula, insertvar)
mydb.commit()
username.set("")
password.set("")
def register():
global screen1
screen.withdraw()
screen1 = Toplevel(screen)
screen1.title("Registration")
screen1.geometry("500x250+700+350")
global username
global password
global username_entry
global password_entry
username = StringVar()
password = StringVar()
Label(screen1, text = " Please Enter Your Details Below", bg = "black", width = w , height = h, font = ("Calibri", 20) , fg = "white").pack()
Label(screen1, text = "").pack()
Label(screen1, text = "Username").place(x=220, y=85)
username_entry = Entry(screen1, textvariable = username, width="50").place(x=100, y=110)
Label(screen1, text = "Password").place(x=220, y=135)
password_entry = Entry(screen1, textvariable = password, width="50").place(x=100, y=160)
Button(screen1, text= "Register", height="1", width="20", command = register_user).place(x=80, y=200)
Button(screen1, text="Cancel", height="1", width="20", command= on_closereg).place(x=270, y=200)
screen1.protocol("WM_DELETE_WINDOW", on_closereg)
def login():
global screen2
mydb = mysql.connector.connect(
host="localhost",
user="root",
passwd="root",
database="loginsystem"
)
mycursor = mydb.cursor()
sql_select_Query = "select * from users"
mycursor.execute(sql_select_Query)
records = mycursor.fetchall()
for row in records:
print("Username" , row[1],)
print("Password", row[2], "\n" )
mycursor.close()
screen.withdraw()
screen2 = Toplevel(screen)
screen2.title("HOT or SUPER HOT")
screen2.geometry("800x600+550+220")
screen2.protocol("WM_DELETE_WINDOW", on_close)
def checker():
if len(username.get()) == 0 and len(password.get()) == 0:
print("Please fill in the Missing Info")
def on_close():
screen2.withdraw()
screen.update()
screen.deiconify()
screen.lift()
def on_closereg():
screen1.withdraw()
screen.update()
screen.deiconify()
screen.lift()
def verify():
global name
global userlogcred
global userpascred
userlogcred = username_verify.get()
userpascred = password_verify.get()
loadname = ("SELECT Username FROM users WHERE Username =%s")
loadpass = ("SELECT Password FFROM users WHERE Password =%s")
mydb = mysql.connector.connect(
host="localhost",
user="root",
passwd="root",
database="loginsystem"
)
mycursor = mydb.cursor()
if len(username_verify.get()) == 0 and len(password_verify.get()) == 0:
print("Please fill in the Missing Info")
if len(username_verify.get()) == 0 and len(password_verify.get()) != 0 :
print("Please Enter a Username")
elif len(username_verify.get()) != 0 and len(password_verify.get()) == 0:
print("Please enter a Password")
else:
mycursor.execute(loadname, userlogcred)
mycursor.execute(loadpass, userpascred)
logincheck = mycursor.fetchone()
loginpasscheck = mycursor.fetchone()
if logincheck is None:
print("Sorry, could not find you in the database\nOr it just isn't working")
if logincheck is not None and loginpasscheck is None:
print("Please Enter your Password")
elif logincheck is None and loginpasscheck is not None:
print("Please enter Your Username")
else:
print("pass\nSuccessfully loaded {} from the database".format(username_verify.get()))
def main_Screen():
global screen
screen = Tk()
screen.geometry("600x300+650+350")
screen.title("Login System")
Label(text = "Login System" , bg = "black", width = w , height = h, font = ("Calibri", 20) , fg = "white").pack()
Label(text = "").pack()
Button(text = "Login", height = h, width = "30", command = verify).place(x=50 , y=200)
Label(text = "").pack()
Button(text = "Register" ,height = h, width = "30", command = register).place(x=320 , y=200)
global username_verify
global password_verify
username_verify = StringVar()
password_verify = StringVar()
Label(screen, text = "Username").place(x=265, y = 90)
username_entry1 = Entry(screen, textvariable = username_verify, width = "80").place(x=57, y=110)
Label(screen, text="Password").place(x=267, y=140)
password_entry1 = Entry(screen, textvariable = password_verify, width = "80").place(x=57, y=160)
screen.mainloop()
main_Screen()
print("Hello World")
Update I Found this code and I'm trying to apply it to my project where in this code compares the input value inside the textbox to the database data and it checks if the datas are already present if they are it then sends you to another form.
def verify():
global name
loadname = ("SELECT Username FROM users WHERE Username =%s")
loadpass = ("SELECT Password FFROM users WHERE Password = %s")
mydb = mysql.connector.connect(
host="localhost",
user="root",
passwd="root",
database="loginsystem"
)
mycursor = mydb.cursor()
if len(username_verify.get()) == 0 and len(password_verify.get()) == 0:
print("Please fill in the Missing Info")
if len(username_verify.get()) == 0 and len(password_verify.get()) != 0 :
print("Please Enter a Username")
elif len(username_verify.get()) != 0 and len(password_verify.get()) == 0:
print("Please enter a Password")
else:
mycursor.execute(loadname, username_verify.get())
mycursor.execute(loadpass, password_verify.get())
logincheck = mycursor.fetchone()
loginpasscheck = mycursor.fetchone()
if logincheck is None:
print("Sorry, could not find you in the database\nOr it just isn't working")
if logincheck is not None and loginpasscheck is None:
print("Please Enter your Password")
elif logincheck is None and loginpasscheck is not None:
print("Please enter Your Username")
else:
print("pass\nSuccessfully loaded {} from the database".format(login))
but I encountered this erro please help.
Traceback (most recent call last):
File "C:\Users\lenovo\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:/Users/lenovo/PycharmProjects/Pylog/App.py", line 141, in verify
mycursor.execute(loadname, username_verify.get())
File "C:\Users\lenovo\PycharmProjects\Pylog\venv\lib\site-packages\mysql\connector\cursor.py", line 569, in execute
self._handle_result(self._connection.cmd_query(stmt))
File "C:\Users\lenovo\PycharmProjects\Pylog\venv\lib\site-packages\mysql\connector\connection.py", line 553, in cmd_query
result = self._handle_result(self._send_cmd(ServerCmd.QUERY, query))
File "C:\Users\lenovo\PycharmProjects\Pylog\venv\lib\site-packages\mysql\connector\connection.py", line 442, in _handle_result
raise errors.get_exception(packet)
mysql.connector.errors.ProgrammingError: 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%s' at line 1
Hello World
Update I put the username_verify.get() values into variables still didn't work and it still posts the same error.
import mysql.connector as sql
class connections:
__HOST = 'localh`o`st'
__USERNAME = 'root'
__PASSWORD = ''
__DATABASE = 'testing'
def __init__(self):
self.con = sql.connect(host=connections.__HOST,user=connections.__USERNAME,password=connections.__PASSWORD,database=connections.__DATABASE)
def connect_database(self,username,password):
#append password and username in the emptey list below for later checkings
mypassword_queue =[]
sql_query = "SELECT *FROM users WHERE first_name ='%s' AND password ='%s'" % (username, password)
mycursor = self.con.cursor()
try:
mycursor.execute(sql_query)
myresults =mycursor.fetchall()
for row in myresults:
for x in row:
mypassword_queue.append(x)
except:
print('error occured')
if (username and password) in mypassword_queue:
print('there is something')
else:
print('there is no anything')
self.con.close()
root = connections()
#---you must have created a database with choice of your database name for this case it is testing
#---- the data inside has name as tumusiime and password 1234
root.connect_database('tumusiime','1234')
I will give you a code that works for me for all querys with mysql.connector
**config= {'user': your_user',
'password': 'your_pass',
'host': 'ip_of_your_db',
'database': 'name_of_your_db',
'raise_on_warnings': True}
def run_query(self,query):
try:
conn = mysql.connector.connect(**self._config)
if conn.is_connected():
print('run_query: Connecting MySql Db')
cur = conn.cursor()
cur.execute(query)
r= cur.fetchall()
return r
except mysql.connector.Error as err:
if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
print("run_query: Error in username or password")
elif err.errno == errorcode.ER_BAD_DB_ERROR:
print("run_query: Dabatase doesn't exist")
else:
print(err)
finally:
conn.commit()
conn.close()
and each Query need to have this format
query='SELECT * FROM {}'.format("your_db.your_table")
answer=self.run_query(query)

After text widget opens, tkinter GUI crashes/does not respond whenever its closed

Right now, after I press the 'Time Range' button and call the calculateTime function, the text widget would appear with the results that I've inserted into it. However, after that, whenever I close the GUI window, the program would freeze and I'll have to forced quit it. This is my code:
import tkinter
from tkinter import *
import math
from tkinter import messagebox
class MyClass(tkinter.Frame):
def __init__(self, *args, **kwargs):
tkinter.Frame.__init__(self, *args, **kwargs)
#Setting up frame and widgets
vcmd1 = (self.register(self.__vcmd1), '%P', '%S')
vcmd2 = (self.register(self.__vcmd2), '%P')
vcmd3 = (self.register(self.__vcmd3), '%P', '%S')
label_iso = Label(self,text="Isotope A, Element")
label_vol = Label(self, text="Voltage")
label_range = Label(self, text="Charge Range")
label_iso.grid(row=0, column=0, sticky=E)
label_vol.grid(row=1, column=0, sticky=E)
label_range.grid(row=2, column=0, sticky=E)
self.entry1 = tkinter.Entry(self, validate="key", validatecommand=vcmd1)
self.entry2 = tkinter.Entry(self, validate="key", validatecommand=vcmd2)
self.entry3 = tkinter.Entry(self, validate="key", validatecommand=vcmd3)
self.entry1.grid(row=0, column=1)
self.entry2.grid(row=1, column=1)
self.entry3.grid(row=2, column=1)
def __vcmd1(self, P, S):
validString = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM,1234567890'
if not S in validString:
return False
if "," in P:
if (len(P) - 1) > len(P.replace(",","")):
return False
messagebox.showinfo("Error", "Expected Form: ex. 133,Cs")
else:
return True
def __vcmd2(self, P):
if P == '':
return True
try:
float(P)
return True
except ValueError:
messagebox.showinfo("Error", "Entry is not a float or integer")
return False
def __vcmd3(self, P, S):
if "," in P:
if len(P.split(",")) > 2:
return False
a = P.split(",")[0]
b = P.split(",")[1]
if a != '' and b != '':
try:
int(a)
int(b)
except ValueError:
messagebox.showinfo("Error", "Expected form: ex. 1,12")
return False
else:
return True
class TimeGenerator:
def __init__(self,master):
frame = MyClass(master)
frame.grid(columnspan=2)
button = Button(root, text='Time Range', command=self.calculateTime)
button.grid(row=3, columnspan=2)
self.text = Text(root)
self.iso = frame.entry1
self.vol = frame.entry2
self.r = frame.entry3
def calculateTime(self):
x = 5
if self.r.get() == "" or self.iso.get() == "" or self.vol.get() == "":
messagebox.showinfo("Error", "No field can be empty")
return None
self.iso = self.iso.get().replace(" ", "")
list = []
for e in self.iso.split(","):
list.append(e)
f = open("/Users/LazyLinh/PycharmProjects/mass.mas12.txt", "r")
i = 0
while (i < 40):
header = f.readline()
i += 1
self.mass = 0
#iterate through text file
for line in f:
line = line.strip()
columns = line.split()
if (list[0] == columns[3]):
if (list[1].lower() == columns[4].lower()):
if (len(columns) == 16):
self.mass = float(columns[13].replace("#","")) + float(columns[14].replace("#",""))
else:
self.mass = float(columns[12].replace("#","")) + float(columns[13].replace("#",""))
#Calculation
self.r = self.r.get().replace(" ", "")
tup = tuple(int(x) for x in self.r.split(","))
list = []
for q in range(tup[0], tup[1] + 1):
y = (x * math.sqrt(self.mass * 1.6605402e-27 / (2 * q * float(self.vol.get())))) * 10e6
list.append(y)
i = tup[0]
#inserting to text widget
for time in list:
self.text.insert("end", "%d: %s\n" % (i, time))
i = i + 1
self.text.pack()
root = Tk()
b = TimeGenerator(root)
root.mainloop()
I've tried to searched up on this topic, but I'm not really using any weird update() function, and text shows up after the function is finished, so how likely that it is an event loop problem? Am I also doing something wrong that could cause this problem?
Thank you!
You have widgets in the root window that use both pack and grid. You cannot do this. Within a given container (root window, frame, etc) you can use one or the other, but not both.
The reason your program freezes is due to pack and grid fighting to gain control of the layout. When you pack the text widget it causes a change in the size and/or position of other widgets in the root window. That triggers grid to try to re-layout the widgets it is responsible for. This triggers pack to try to re-layout the widgets it is responsible for, and on and on until the end of time.
My guess is that you need to use grid with self.text since you use grid everywhere else.

Display of a large amount of data in a Canvas with a Scrollbar

I'm having a problem trying to display a large table in tkinter.
First, I tried to display all label at once in the canvas, but over few hundred rows, the program shut down. So I tried to create a scrollable canvas that updates everytime I scroll: I collect the position of the scrollbar and depending on the position of it, I display the 10 values corresponding.
But I can't get this code working. For now it only displays a black background with the scrollbar on the right.
Here is the code:
from tkinter import *
class Application(object):
def __init__(self, parent):
self.x = []
for i in range(1, 1000):
self.x.append(i)
self.parent = parent
self.mainFrame = Frame(self.parent)
self.mainFrame.pack()
self.canvas = Canvas(self.mainFrame, width = 200, height = 500, bg = "black")
self.canvas.grid(row = 0, column = 0)
self.scroll = Scrollbar(self.mainFrame, orient = VERTICAL, command = self.update)
self.scroll.grid(row = 0, column = 1)
self.canvas.configure(yscrollcommand = self.scroll.set)
self.tabCursor = 0
self.scrollPosition = self.scroll.get()
def update(self):
self.tabCursor = round(self.scrollPosition[0]*len(self.x))
if ((len(self.x) - self.tabCursor) < 10):
self.tabCursor = len(self.x) - 10
for i in range(0, 10): #display 10 values
label = Label(self.canvas, text = str(self.x[tabCursor + i]), width = 50)
label.grid(column = 0, row = i)
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()
EDIT :
I finally had time to implement your answer. It looks fine but I can't get the scrollbar working and i don't know why.
class TableauDeDonnees(object):
"Tableau de données -- Onglet Tableau de données"
def __init__(self, data, parent):
self.parent = parent
self.data = data
print(self.data[0], self.data[1])
print(len(self.data[0]), len(self.data[1]))
self.labels = []
self.navigationFrame = Frame(self.parent)
self.canvas = Canvas(self.parent, bg = "black", width = 200, height = 500)
self.mainFrame = Frame(self.canvas)
self.navigationFrame.pack()
print(len(data))
for row in range(50):
for column in range(len(data)):
self.labels.append(Label(self.canvas, text = str(data[column][row])))
for i in range(len(self.labels)):
self.labels[i].grid(row = i // 2, column = i % 2, sticky = NSEW)
self.boutonRetour = Button(self.navigationFrame, text = "Retour", command = lambda: self.move(-2))
self.quickNav = Entry(self.navigationFrame, width = 3)
self.quickNav.bind('<Return>', lambda x: self.move(self.quickNav.get()))
self.boutonSuivant = Button(self.navigationFrame, text = "Suivant", command = lambda: self.move(0))
temp = divmod(len(data[0]), len(self.labels) // 2)
self.pages = temp[0] + (1 if temp[1] else 0)
self.position = Label(self.navigationFrame, text='Page 1 sur ' + str(self.pages))
self.pageCourante = 1
self.boutonRetour.grid(row = 0, column = 0)
self.quickNav.grid(row = 0, column = 1)
self.boutonSuivant.grid(row = 0, column = 2)
self.position.grid(row = 0, column = 3)
self.scroll = Scrollbar(self.parent, orient = VERTICAL, command = self.canvas.yview)
self.canvas.configure(yscrollcommand = self.scroll.set)
self.scroll.pack(side = RIGHT, fill='y')
self.canvas.pack(side = LEFT, fill = 'both')
self.canvas.create_window((4,4), window = self.mainFrame, anchor = "nw", tags = "frame")
self.canvas.configure(yscrollcommand = self.scroll.set)
self.mainFrame.bind("<Configure>", self.update)
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
def update(self, event):
self.canvas.configure(scrollregion = self.canvas.bbox("all"))
def move(self, direction):
if (self.pageCourante == 1 and direction == -2) or (self.pageCourante == self.pages and direction == 0):
return
if direction in (-2, 0):
self.pageCourante += direction + 1
else:
try:
temp = int(direction)
if temp not in range(1, self.pages + 1):
return
except ValueError:
return
else:
self.pageCourante = temp
for i in range(len(self.labels)):
try:
location = str(self.data[i % 2][len(self.labels)*(self.pageCourante - 1) + i])
except IndexError:
location = ''
self.labels[i].config(text = location)
self.position.config(text = 'Page ' + str(self.pageCourante) + ' sur ' + str(self.pages))
I don't understand why the scrollbar isn't working properly. Note, that my parent is a notebook.
Also, there is a problem with the number of items displayed. The number of pages is right but it seems it displays more than it should cause last pages are empty and the last values displayed seems right.
Thank you for your attention
The scrollbar doesn't work by continuously creating new widgets ad infinitum. You were also missing some key parts - unfortunately, Scrollbar isn't as straightforward as most tkinter widgets.
from tkinter import *
class Application(object):
def __init__(self, parent):
self.parent = parent
self.canvas = Canvas(self.parent, bg='black', width = 200, height = 500)
self.mainFrame = Frame(self.canvas)
self.scroll = Scrollbar(self.parent, orient = VERTICAL, command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.scroll.set)
self.scroll.pack(side='right', fill='y')
self.canvas.pack(side='left', fill='both')
self.canvas.create_window((4,4), window=self.mainFrame, anchor="nw", tags="frame")
self.canvas.configure(yscrollcommand = self.scroll.set)
self.mainFrame.bind("<Configure>", self.update)
self.x = []
for i in range(1000):
self.x.append(Label(self.mainFrame, text=str(i)))
self.x[i].grid()
def update(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()
If you'd like to show only a few at a time and provide a forum-like interface, you can use Buttons to navigate between pages. This example allows the user to navigate with Back and Forward buttons, as well as by entering a page number in the box and pressing Enter.
from tkinter import *
class Application(object):
def __init__(self, parent):
self.x = list(range(1000))
self.labels = []
self.parent = parent
self.navigation_frame = Frame(self.parent)
self.canvas = Canvas(self.parent, bg='black', width = 200, height = 500)
self.mainFrame = Frame(self.canvas)
self.navigation_frame.pack()
for i in range(100):
self.labels.append(Label(self.mainFrame, text=str(i)))
self.labels[i].grid()
self.back_button = Button(self.navigation_frame, text='Back', command=lambda: self.move(-2))
self.quick_nav = Entry(self.navigation_frame, width=3)
self.quick_nav.bind('<Return>', lambda x: self.move(self.quick_nav.get()))
self.forward_button = Button(self.navigation_frame, text='Forward', command=lambda: self.move(0))
temp = divmod(len(self.x), len(self.labels))
self.pages = temp[0] + (1 if temp[1] else 0)
self.you_are_here = Label(self.navigation_frame, text='Page 1 of ' + str(self.pages))
self.current_page = 1
self.back_button.grid(row=0, column=0)
self.quick_nav.grid(row=0, column=1)
self.forward_button.grid(row=0, column=2)
self.you_are_here.grid(row=0, column=3)
self.scroll = Scrollbar(self.parent, orient = VERTICAL, command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.scroll.set)
self.scroll.pack(side='right', fill='y')
self.canvas.pack(side='left', fill='both')
self.canvas.create_window((4,4), window=self.mainFrame, anchor="nw", tags="frame")
self.canvas.configure(yscrollcommand = self.scroll.set)
self.mainFrame.bind("<Configure>", self.update)
def update(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def move(self, direction):
if (self.current_page == 1 and direction == -2) or (self.current_page == self.pages and direction == 0):
return
if direction in (-2, 0):
self.current_page += direction + 1
else:
try:
temp = int(direction)
if temp not in range(1, self.pages+1):
return
except ValueError:
return
else:
self.current_page = temp
for i in range(len(self.labels)):
try:
location = str(self.x[len(self.labels)*(self.current_page - 1) + i])
except IndexError:
location = ''
self.labels[i].config(text=location)
self.you_are_here.config(text='Page ' + str(self.current_page) + ' of ' + str(self.pages))
if __name__ == '__main__':
root = Tk()
app = Application(root)
root.mainloop()

Resources