How to move Tkinter widget precisely. Place method not working - python

Here's the code so far:
# -*- coding: utf-8 -*-
from Tkinter import *
#Creates game window
master = Tk()
master.geometry("640x480")
master.resizable(width = False, height = False)
master.title("YeeHaw Poker")
#Divides window into subsections
menuFrame = Frame(master, bg = "black", height = 60)
menuFrame.pack(fill = X, side = TOP)
tableFrame = Frame(master, highlightbackground = "black", highlightthickness = 4)
tableFrame.pack(fill = BOTH, expand = True)
optionsFrame = Frame(master, bg = "black", height = 100)
optionsFrame.pack(fill = X, side = BOTTOM)
#Draws poker table decorations
tableDecorations = Canvas(tableFrame, bg = "#771427", highlightthickness = 0)
tableDecorations.pack(fill = BOTH, expand = True)
#Renders window thus far so that dimensions can be found
master.update()
tWidth = tableDecorations.winfo_width()
tHeight = tableDecorations.winfo_height()
#Main edge
gap = 10
tableDecorations.create_rectangle(gap, gap, tWidth - gap, tHeight - gap, fill ="#277714", width = 4)
#Table outline
gap = 30
tableDecorations.create_rectangle(gap, gap, tWidth - gap, tHeight - gap, outline = "#35a31b", width = 2)
#Card outline coordinates
cardNum = 5
cardSize = 20
cardHeight = cardSize * 3.5
cardWidth = cardSize * 2.5
cardSpace = 10
cardTop = tHeight / 4
cardLeft = (tWidth - (cardNum * (cardWidth + cardSpace))) / 2
cardY1 = cardTop + cardHeight
cardY2 = cardTop
cardX1 = [0 for i in range(0, cardNum)]
cardX2 = [0 for i in range(0, cardNum)]
suit = [0 for i in range(0, cardNum)]
for i in range(0, cardNum):
cardX1[i] = cardLeft + (i * (cardWidth + cardSpace))
cardX2[i] = cardX1[i] + cardWidth
suit[i] = Label(tableDecorations, text = "", bg = "white", font = (None, 50))
suit[i].place(x = 5000, y = 5000)
#Draws specified card in specified place
def drawCard(pos, type, pip):
if type == "empty":
tableDecorations.create_rectangle(cardX1[pos], cardY1, cardX2[pos], cardY2, outline = "#35a31b", width = 2)
suit[pos].pack_forget()
else:
tableDecorations.create_rectangle(cardX1[pos], cardY1, cardX2[pos], cardY2, fill = "white", outline = "grey", width = 1)
if type == "diamond":
suit[pos].config(text = "♦", fg = "red")
elif type == "heart":
suit[pos].config(text = "♥", fg = "red")
elif type == "spade":
suit[pos].config(text = "♠", fg = "black")
elif type == "club":
suit[pos].config(text = "♣", fg = "black")
suit[pos].pack()
#Creates new table
def newTable():
for i in range(0, cardNum):
drawCard(i, "diamond", 0)
newTable()
master.mainloop()
However this doesn't move the labels with the diamonds in at all, as shown here:
It's infuriating...
I'm wanting the diamond to appear on each individual card, but clearly that's not happening here...
Any ideas?

Related

When I destroy my tkinter root, a gray window pops up that i have to close, how can i fix it

my code is working as I want it to, but I am having a problem when i destroy my root, a gray window pops that i also have to close for the rest of my code to work and function, this is a small issue i would like to fix, could anyone help me with fixing this small issue because it is really annoying me, here is my code:
import face_recognition
import os
import cv2
from face_recognition.api import face_locations
import tkinter as tk
used_list = []
image_list= os.listdir("Faces")
class_names = []
add_key = 0
width = '400'
height = '700'
width_int = int(width)
height_int = int(height)
but_height = height_int / len(image_list)
but_width = width_int / len(image_list)
lbl_add = but_height / 2
but_width = int(but_width)
but_height = int(but_height)
root = tk.Tk()
root.geometry(f"{width}x{height}")
for fle in image_list:
def fun2(fle):
if len(used_list) < 2:
used_list.append(fle)
if len(used_list) == 2:
root.destroy()
cur_but = tk.Button(root,width = but_width,height = height_int,bg='#8a081e',command = lambda i=fle:fun2(i))
cur_but.place(x = 0,y = add_key)
add_key += but_height
for thing in image_list:
txt = tk.Label(root,text = f"{thing}",bg='#8a081e',fg = 'white')
txt.place(x = (width_int / 2) - 30,y =lbl_add)
lbl_add += but_height
big_text = tk.Label(root,text = ' Pick Two Files to see if both people have matching faces',width = 100,height = 5, anchor='w')
big_text.place(x=0,y=0)
root.mainloop()
image_list= os.listdir("Faces")
add_key = 0
width = '400'
height = '800'
width_int = int(width)
height_int = int(height)
but_height = height_int / len(image_list)
but_width = width_int / len(image_list)
but_width = int(but_width)
root = tk.Tk()
root.geometry(f"{width}x{height}")
for file_name in image_list:
tk.Button(root,text = f'{file_name}',width = but_width,height = height_int)
root.mainloop()
print()
img1 = used_list[0]
img2 = used_list[1]
def check_two_faces(image1,image2):
class_names = []
image1 = 'Faces/' + image1
image2 = 'Faces/' + image2
read_image = cv2.imread(image1)
Steve_image = face_recognition.load_image_file(image1)
Steve_image = cv2.cvtColor(Steve_image,cv2.COLOR_BGR2RGB)
second_pic = face_recognition.load_image_file(image2)
second_pic = cv2.cvtColor(second_pic,cv2.COLOR_BGR2RGB)
face_loc = face_recognition.face_locations(Steve_image)[0]
face_enc = face_recognition.face_encodings(Steve_image)[0]
cv2.rectangle(Steve_image, (face_loc[3],face_loc[0]), ( face_loc[1],face_loc[2]), (0, 255, 0), 2)
second_loc = face_recognition.face_locations(second_pic)[0]
second_enc = face_recognition.face_encodings(second_pic)[0]
cv2.rectangle(second_pic, (second_loc[3],second_loc[0]), ( second_loc[1],second_loc[2]), (0, 255, 0), 2)
comparision = face_recognition.compare_faces([face_enc],second_enc)
print()
name = os.path.splitext(image1)[0]
if comparision == [False]:
print("Both pictures are different people.")
else:
print(f"""Both pictures are the same people.
""")
check_two_faces(image1=img1,image2=img2)

What's making my tkinter graphics so slow?

I'm trying to implement GUI editing tool by python.
I implemented preliminary code to test how work well.
However, it is too slow to use even if small sample case.
My code is below:
import numpy as np
from tkinter import *
nx=10
ny=8
world=np.zeros((ny,nx))
world[:,3]=1
world[1,:]=1
# Tkinter ========
root = Tk()
root.title("make Land/Sea mask")
root.resizable(0,0)
menu_ROOT = Menu(root)
root.configure(menu = menu_ROOT)
menu_GAME = Menu(menu_ROOT, tearoff = False)
menu_ROOT.add_cascade(label = 'Menu', under = 4, menu = menu_GAME)
###Frame objects###
root_frame = Frame(root, relief = 'groove', borderwidth = 5, bg = 'LightGray')
game_frame = Frame(root_frame, relief = 'sunken', borderwidth = 3, bg = 'LightGray')
root_frame.pack()
game_frame.pack(pady = 5, padx = 5)
def create_map(world,nx,ny):
c = 0
frame_list = []
for j in np.arange(ny):
for i in np.arange(nx):
if world[j,i]==1:
frame = Frame(game_frame, width = 20, height = 20, bd = 0.5, relief = 'groove', bg = 'yellow green')
else:
frame = Frame(game_frame, width = 20, height = 20, bd = 0.5, relief = 'ridge', bg = 'pale green')
frame.num = c
frame_list.append(frame)
frame.grid(row=j, column=i)
c += 1
create_map(world,nx,ny)
root.mainloop()
In this case, I set 10x8 matrix, but I finally will use 360x180 matrix and it may takes an enormous amount of time to draw.
Does anyone know how improve this code?
You shouldn't use Tkinter for this purpose.
Here's an example in PyGame, which in my opinion is pretty easy to learn:
import sys
import time
import pygame
import numpy as np
DISPLAY_SIZE = 840, 680
def generate_map(nx, ny):
return np.rint(np.random.rand(ny, nx))
def render_map(world, display, selected_img, unselected_img, img_size):
for j in np.arange(world.shape[0]):
for i in np.arange(world.shape[1]):
if world[j, i] == 1:
display.blit(selected_img, (i * img_size[0], j * img_size[0]))
else:
display.blit(unselected_img, (i * img_size[0], j * img_size[0]))
display = pygame.display.set_mode(DISPLAY_SIZE, pygame.HWSURFACE | pygame.DOUBLEBUF)
selected = pygame.image.load("selected_cell.png")
unselected = pygame.image.load("unselected_cell.png")
img_size = selected.get_size() # Assuming both images are the same size
clock = pygame.time.Clock()
world = generate_map(26, 21)
fps_counter_time = time.perf_counter()
while True:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit(0)
render_map(world, display, selected, unselected, img_size)
pygame.display.flip()
if (time.perf_counter() - fps_counter_time) > 0.1:
pygame.display.set_caption("FPS: %.4f" % (clock.get_fps(),))
fps_counter_time = time.perf_counter()

Image and labels won't appear in Tkinter

I wanted to make a configuration menu where the user can select their language options and the resolution the game will run at. However, the labels for the language select and the image that is supposed to appear at the bottom do not display at all.
Language Label:
#Langauge Radio Buttons
Langlabel = Label(ConfigWindow, textvariable="Languages")
EngButton = Radiobutton(ConfigWindow, text = "English",variable = EngSelect, value = 1)
JapButton = Radiobutton(ConfigWindow, text = "Japanese", variable = JapSelect, value = 1)
#Buton Placements
Langlabel.place(x = 100,y = 20)
EngButton.place(x = 100,y = 50)
JapButton.place(x = 180,y = 50)
Langlabel.pack()
Image:
#Game Image
TestImage = ImageTk.PhotoImage(Image.open("TestMap.png"))
canvas.create_image(x = 100, y = 100, anchor=NW, image=TestImage)
ConfigWindow.mainloop()
Thanks in advance.
This happens because Python garbage collects the images because they have no reference to them. This can be fixed by assigning the created images/labels to an array or variable:
class ConfigWindow:
images = []
labels = []
def setup(self):
#Langauge Radio Buttons
Langlabel = Label(ConfigWindow, textvariable="Languages")
EngButton = Radiobutton(ConfigWindow, text = "English",variable = EngSelect, value = 1)
JapButton = Radiobutton(ConfigWindow, text = "Japanese", variable = JapSelect, value = 1)
self.labels.push(Langlabel)
self.labels.push(EngButton)
self.labels.push(JapButton)
#Buton Placements
Langlabel.place(x = 100,y = 20)
EngButton.place(x = 100,y = 50)
JapButton.place(x = 180,y = 50)
Langlabel.pack()
def load_images(self):
TestImage = ImageTk.PhotoImage(Image.open("TestMap.png"))
self.images.add(TestImage);
canvas.create_image(x = 100, y = 100, anchor=NW, image=TestImage)

Tkinter not letting me insert a text in a Text Widget

from tkinter import *
from PIL import Image, ImageTk
import time
schermata = Tk()
screen_width = schermata.winfo_screenwidth()
screen_height = schermata.winfo_screenheight()
indice = 0
schermata.iconbitmap("immagini\icona.ico")
screen_resolution = str(screen_width)+'x'+str(screen_height)
large_font = ('Verdana',30)
schermata.geometry(screen_resolution)
schermata.title("Jovan's RPG")
class GUI(Frame):
def __init__(self, master):
super(GUI, self).__init__(master)
self.pack()
self.bg()
self.immagine()
self.testo()
self.statistiche()
self.inserimenti()
def bg(self):
load = Image.open("immagini\\background.png")
render = ImageTk.PhotoImage(load)
img = Label(schermata, image = render)
img.image = render
img.pack()
def immagine(self):
load = Image.open("immagini\\dn.png")
render = ImageTk.PhotoImage(load)
img = Label(schermata, image = render)
img.image = render
img.place( x = 10, y = 10 )
def testo(self):
self.testo = Text(schermata, width = 110, height = 35, border = 5, bg = "black", fg ="white")
self.testo.place( x = 400, y = 20 )
def statistiche(self):
self.stats = Text(schermata, width = 40, height = 10, border = 5, bg = "black", fg ="white")
self.stats.place( x = 10, y = (screen_height - 200))
def inserisci(self):
fraseInserita = self.inserimento.get()
scrivere(fraseInserita)
self.inserimento.delete('0', END)
def inserimenti(self):
self.inserimento = Entry(schermata,font=large_font, width = 25, border = 5, bg = "black", fg ="white")
self.inserimento.place( x = 400, y = (screen_height - 100))
self.bottone = Button(schermata, width = 30, height = 3, border = 5, text = "Inserisci", command = self.inserisci)
self.bottone.place( x = (screen_width - 300), y = (screen_height - 100))
g = GUI(schermata)
def scrivere(scrittura):
g.testo.insert('1.0', scrittura)
def cancellaTesti():
g.testo.delete('0',END)
def wait(secondi):
time.sleep(secondi)
Levels class
from GUI import *
g = GUI(schermata)
class Livelli():
def __init__(self): pass
def cicloLivelli(self):
self.presentazione()
def presentazione(self):
scrivere("Salve avventuriero, qual e' il tuo nome?")
Main
from GUI import *
a = GUI(schermata)
l = Livelli()
if __name__ == "__main__":
a.mainloop()
l.cicloLivelli()
As you see i called the function back[(scrivere)], but the interpreter won't let the string appear in the Text widget. I've just posted the class of the GUI and the class of the "levels" that i'm looking forward to use for creating, of course, my levels for the game i'm creating. I'm searching for an answer and can't find it, hope you guys can help.
The get something on the screen you need to include self.config(width=700, heigh=800) (width and height totally arbitrary :)!) before self.pack() in class GUI and change all schermata into self (as you have defined the instance of GUI as the master frame).
I made the program put something on screen with the version below and I had to define some variables like screen_height, screen_width just so to prove the concept.
I also defined the method scrivere. Anyway it is rendering something so hopefully you can proceed. Good luck.
import tkinter as tk
class GUI(tk.Frame):
def __init__(self):
super(GUI, self).__init__()
self.config(width=700, height=500)
self.pack()
# self.bg()
# self.immagine()
self.testo()
self.statistiche()
self.inserimenti()
def bg(self):
load = Image.open("immagini\\background.png")
render = ImageTk.PhotoImage(load)
img = Label(self, image = render)
img.image = render
img.pack()
def immagine(self):
load = Image.open("immagini\\dn.png")
render = ImageTk.PhotoImage(load)
img = Label(self, image = render)
img.image = render
img.place( x = 10, y = 10 )
def testo(self):
self.testo = tk.Text(self, width = 110, height = 35, border = 5, bg = "black", fg ="white")
self.testo.place( x = 400, y = 20 )
def statistiche(self):
screen_height = 400
self.stats = tk.Text(self, width = 40, height = 10, border = 5, bg = "black", fg ="white")
self.stats.place( x = 10, y = (screen_height - 200))
def inserisci(self):
fraseInserita = self.inserimento.get()
self.scrivere(fraseInserita)
self.inserimento.delete('0', 'end')
def inserimenti(self):
large_font = ('calibri', 12)
screen_height = 400
screen_width = 600
self.inserimento = tk.Entry(self,font=large_font, width = 25, border = 5, bg = "black", fg ="white")
self.inserimento.place( x = 400, y = (screen_height - 100))
self.bottone = tk.Button(self, width = 30, height = 3, border = 5, text = "Inserisci", command = self.inserisci)
self.bottone.place( x = (screen_width - 300), y = (screen_height - 100))
def scrivere(self, frase):
print(' you need to define this function when button is pressed')
class Livelli():
def __init__(self):
pass
def cicloLivelli(self):
self.presentazione()
def presentazione(self):
print("Salve avventuriero, qual e' il tuo nome?")
if __name__ == "__main__":
a = GUI()
l = Livelli()
l.cicloLivelli()
a.mainloop()

python 3 tkinter class variables and Spinboxes with Labels not updating

Can't figure out why my labels aren't updating from clicks on my Spinboxes
from tkinter import *
mainBackground = "#0047BF"
mainForeground = "#C2F2E6"
inputBackground = "#230E38"
window = Tk()
window.title("Gurps Game Manager")
window.geometry("700x600")
window.wm_iconbitmap('pyramid.ico')
window.configure(background = mainBackground)
# Creating Variable Classes and setting to base stat
strength = IntVar(window)
strength.set(10)
dexterity = IntVar(window)
dexterity.set(10)
intelligence = IntVar(window)
intelligence.set(10)
health = IntVar(window)
health.set(10)
hpMod = IntVar(window)
hpMod.set(0)
willMod = IntVar(window)
willMod.set(0)
perMod = IntVar(window)
perMod.set(0)
fpMod = IntVar(window)
fpMod.set(0)
bSpeedMod = IntVar(window)
bSpeedMod.set(0)
bMoveMod = IntVar(window)
bMoveMod.set(0)
hpTotal = IntVar(window)
hpTotal.set(10)
willTotal = IntVar(window)
willTotal.set(10)
perTotal = IntVar(window)
perTotal.set(10)
fpTotal = IntVar(window)
fpTotal.set(10)
bSpeedTotal = IntVar(window)
bSpeedTotal.set(5)
bMoveTotal = IntVar(window)
bMoveTotal.set(5)
bLift = IntVar(window)
bLift.set(20)
bThrust = StringVar(window)
bThrust.set('1d-2')
bSwing = StringVar(window)
bSwing.set('1d')
charPointTotal = IntVar(window)
charPointTotal.set(0)
charPointLimit = IntVar(window)
charPointLimit.set(250)
charPointDiff = IntVar(window)
charPointDiff.set(250)
# Functions to create widgets
def mainLabel(text):
label = Label(window, text = text, bg = mainBackground, fg = mainForeground,
font = ('Lucida Console', 14))
return label
def calcLabel(textVariable):
label = Label(window, textvariable = textVariable, bg = mainBackground, fg = mainForeground, font = ('Lucida Console', 14))
return label
def mainEntry(callback = None):
entry = Entry(window, bg = inputBackground, fg = mainForeground, insertbackground = mainForeground,
command = callback)
return entry
def mainSpinbox(callback, textVar, floor, ceiling, increment = 1):
spinbox = Spinbox(window, fg = mainForeground, state = 'readonly', readonlybackground = mainBackground,
from_ = floor, to = ceiling, increment = increment, textvariable = textVar, command = callback,
justify = 'center', border = '0', width = '5')
return spinbox
# Command function to set values on change
def charPointsCallback():
st = int(strength.get())
dx = int(dexterity.get())
iq = int(intelligence.get())
ht = int(health.get())
hp = int(hpMod.get())
will = int(willMod.get())
per = int(perMod.get())
fp = int(fpMod.get())
bSpeed = int(bSpeedMod.get())
bMove = int(bMoveMod.get())
hpTotal.set(st + hp)
willTotal.set(iq + will)
perTotal.set(iq + per)
fpTotal.set(ht + fp)
bSpeedTotal.set((ht + dx) / 4 + bSpeed)
bMoveTotal.set((ht + dx) // 4 + bMove)
bLift.set((st * st) / 5)
cpTotal = ((st - 10) * 10) + ((dx - 10) * 20) + ((iq - 10) * 20) + ((ht - 10) * 10) + (hp * 2) + (will * 5) + (
per * 5) + (fp * 5) + (bSpeed * 20) + (bMove * 5)
cpLimit = charPointLimit.get()
charPointTotal.set(cpTotal)
charPointDiff.set(cpLimit - cpTotal)
# Lists of strings and variables for loop to create widgets
coreStatLabels = ['ST', 'DX', 'IQ', 'HT']
coreStatVar = [strength, dexterity, intelligence, health]
modStatLabels = ['HP', 'Will', 'Per', 'FP', 'Basic Speed', 'Basic Move']
modStatVar = [hpMod, willMod, perMod, fpMod, bSpeedMod, bMoveMod]
totalStatVar = [hpTotal, willTotal, perTotal, fpTotal, bSpeedTotal, bMoveTotal]
derivedStatLabels = ['Basic Lift', 'Basic Thrust', 'Basic Swing', 'Character Point Total:']
derivedStatVar = [bLift, bThrust, bSwing, charPointTotal]
# Widgets
characterNameLbl = mainLabel('Character Name:')
characterNameLbl.grid(row = 0, column = 0, columnspan = 2)
characterNameEntry = mainEntry(charPointsCallback())
characterNameEntry.grid(row = 0, column = 2)
charPointLimitLbl = mainLabel('Character Point Limit:')
charPointLimitLbl.grid(row = 1, column = 0, columnspan = 2)
charPointLimitSpin = mainSpinbox(charPointsCallback(),charPointLimit, 100, 500, 10)
charPointLimitSpin.grid(row = 1, column = 2)
# Loops that create the widgets
for i in range(4):
row = range(2, 6)
coreStatLbl = mainLabel(coreStatLabels[i])
coreStatLbl.grid(row = row[i], column = 0)
coreStatSpin = mainSpinbox(charPointsCallback(), coreStatVar[i], 5, 15)
coreStatSpin.grid(row = row[i], column = 2)
for i in range(5):
row = range(6, 12)
modStatLbl = mainLabel(modStatLabels[i])
modStatLbl.grid(row = row[i], column = 0)
modStatSpin = mainSpinbox(charPointsCallback(), modStatVar[i], -5, 5)
modStatSpin.grid(row = row[i], column = 1)
totalStatLabel = calcLabel(totalStatVar[i])
totalStatLabel.grid(row = row[i], column = 2)
for i in range(4):
row = range(12,16)
derivedStatLbl = mainLabel(derivedStatLabels[i])
derivedStatLbl.grid(row = row[i], column = 0)
derivedStatCalc = calcLabel(derivedStatVar[i])
derivedStatCalc.grid(row = row[i], column = 2)
window.mainloop()
My understanding of variable classes is that any widget with a variable class set to it will update with the variable when it changes. I click on the up/down spinner, and nothing changes.
When you do this:
modStatSpin = mainSpinbox(charPointsCallback(), ...)
It is exactly the same as if you did this:
something = charPointsCallback()
modStatSpin = mainSpinbox(something, ...)
If you are passing in a callback toa function, you must pass in a reference to the function (ie: remove the trailing ())

Categories