Super new to coding, I have a tkinter GUI with 5 rectangles, an entry box, and a button labelled go. I want to be able to change the color of the rectangles based on the number I enter into the entry box after I hit go. I don't think i'm close? but i have no idea how to proceed. Help would be appreciated. Thanks
from tkinter import *
the_window = Tk()
the_window.title('Show Text Count')
def changelbl():
number=(numberx.get())
if (numberx == 1):
label1.config(fill='green')
numberx=StringVar()
canvas = Canvas(the_window, width=270, height=20)
canvas.pack()
label1 = canvas.create_rectangle(0, 0, 50, 20, fill='grey')
label2 = canvas.create_rectangle(55, 0, 105, 20, fill='grey')
label3 = canvas.create_rectangle(110, 0, 160, 20, fill='grey')
label4 = canvas.create_rectangle(165, 0, 215, 20, fill='grey')
label5 = canvas.create_rectangle(220, 0, 270, 20, fill='grey')
Entrybox = Entry(the_window, bg='grey', width=15, textvariable=numberx)
Entrybox.pack(padx=(60,0), side=LEFT)
Gobutton = Button(the_window, text='Go',command=changelbl)
Gobutton.config(height=1, width=5)
Gobutton.pack(padx=(15,0), side=LEFT)
Here is a corrected version that changes the rectangle colors upon entry of a number in the entrybox, and pressing the Go button:
from tkinter import *
the_window = Tk()
the_window.title('Show Text Count')
def on_Go_button():
try:
num = int(entrybox.get())
except:
num = 3
num = num % 5
canvas.itemconfig(num, fill='green')
numberx=StringVar()
canvas = Canvas(the_window, width=270, height=20)
canvas.pack()
pos = [(0, 0, 50, 20), (55, 0, 105, 20), (110, 0, 160, 20), (165, 0, 215, 20), (220, 0, 270, 20)]
rectangles = [None for _ in range(5)]
for idx in range(5):
rectangles[idx] = canvas.create_rectangle(*pos[idx], fill='grey')
entrybox = Entry(the_window, bg='grey', width=15, textvariable=numberx)
entrybox.pack(padx=(60,0), side=LEFT)
gobutton = Button(the_window, text='Go',command=on_Go_button)
gobutton.config(height=1, width=5)
gobutton.pack(padx=(15,0), side=LEFT)
the_window.mainloop()
This may not be as simple of an answer as you were looking for, but hopefully it will be of some help.
I thought that creating a class would be a better approach for getting your desired result. I also changed changelbl to allow for multiple color options to be retrieved from a dictionary.
In your code, you were missing the line, the_window.mainloop() which will start start running your tkinter window.
from tkinter import *
class ColorBoxes:
def __init__(self, the_window):
self.root = the_window
self.root.title('Show Text Count')
self.canvas = Canvas(self.root, width=270, height=20)
self.canvas.pack()
self.label1 = self.canvas.create_rectangle(0, 0, 50, 20, fill='grey')
self.label2 = self.canvas.create_rectangle(55, 0, 105, 20, fill='grey')
self.label3 = self.canvas.create_rectangle(110, 0, 160, 20, fill='grey')
self.label4 = self.canvas.create_rectangle(165, 0, 215, 20, fill='grey')
self.label5 = self.canvas.create_rectangle(220, 0, 270, 20, fill='grey')
self.entry_box = Entry(self.root, bg='grey', width=15,)
self.entry_box.pack(padx=60, side=LEFT)
self.go_button = Button(self.root, text='Go', command=self.changelbl)
self.go_button.config(height=1, width=5)
self.go_button.pack(padx=15, side=LEFT)
def changelbl(self):
number = self.entry_box.get()
fill_colors = {
'1': 'green',
'2': 'yellow',
'3': 'red'
# can add more colors to this dictionary if needed
}
self.canvas.itemconfig(self.label1, fill=fill_colors.get(number))
self.canvas.itemconfig(self.label2, fill=fill_colors.get(number))
self.canvas.itemconfig(self.label3, fill=fill_colors.get(number))
self.canvas.itemconfig(self.label4, fill=fill_colors.get(number))
self.canvas.itemconfig(self.label5, fill=fill_colors.get(number))
the_window = Tk()
ColorBoxes(the_window)
the_window.mainloop()
Again, this may be more than you were looking for, but hopefully you can pick up on what is going on and learn a bit! Good luck!
Related
This question already has answers here:
Why does Tkinter image not show up if created in a function?
(5 answers)
Closed 6 months ago.
I'm trying to display a frame with a canvas inside in order I'll be able to change of frame with a button, but when the code is executed it does not even display the button, I don't know if it happens because of all is on a function, if doing what I think is even possible or if I'm missing something
from tkinter import *
window = Tk()
window.geometry("1200x700")
window.configure(bg = "#ffffff")
def btn_clicked():
print("Button Clicked")
frame1 =Frame(window, width=1200, height=700)
frame1.grid(row=0, column=0)
def load_page():
frame1.tkraise()
frame1.pack_propagate(False)
canvas = Canvas(
frame1,
bg = "#263ff8",
height = 700,
width = 1200,
bd = 0,
highlightthickness = 0,
relief = "ridge")
canvas.place(x = 0, y = 0)
background_img = PhotoImage(file = f"background.png")
background = canvas.create_image(
601.0, 341.0,
image=background_img)
img0 = PhotoImage(file = f"img0.png")
boton = Button(
image = img0,
borderwidth = 0,
highlightthickness = 0,
command = btn_clicked,
relief = "flat")
boton.place(
x = 85, y = 71,
width = 430,
height = 99)
load_page()
window.resizable(False, False)
window.mainloop()
Rephrased the entire code and including image:
To see button display. I had to reduced height and width in Canvas. Also The button had to reduced. In line 21, I changed bd = 10. You can comment in , because I don't used PhotoImage. you can debug see in image.
from tkinter import *
window = Tk()
window.geometry("1200x700")
window.configure(bg = "#ffffff")
def btn_clicked():
print("Button Clicked")
frame1 =Frame(window, width=1200, height=700)
frame1.grid(row=0, column=0)
def load_page():
frame1.tkraise()
frame1.pack_propagate(False)
canvas = Canvas(
frame1,
bg = "#263ff8",
height = 100,
width = 200,
bd = 10,
highlightthickness = 0,
relief = "ridge")
canvas.place(x = 0, y = 0)
#background_img = PhotoImage(file = f"background.png")
#background = canvas.create_image(
#601.0, 341.0,
#image=background_img)
#img0 = PhotoImage(file = f"img0.png")
boton = Button(frame1,
#image = img0,
borderwidth = 0,
highlightthickness = 0,
command = btn_clicked,
relief = "flat")
boton.place(
x = 85, y = 71,
width = 30,
height =29)
load_page()
window.resizable(False, False)
window.mainloop()
Output result. you can see debug.
I have the following GUI as shown in the Figure below. Instead of the black box, I wanted to draw a transparent rectangle on top of all the scales covering values 1, 0, and -1 of the scale.
Is there a way to make the Tkinter canvas transparent? If it is not the correct way to do it, what are the alternatives that I could try? I shared the sample code I use. That can be used to reproduce this GUI.
from tkinter import *
import itertools
root = Tk()
root.geometry('840x420')
root.title('Test Window')
variables = {"var1", "var2", "var3", "var4"}
pair_list = list(itertools.combinations(list(variables), 2))
pair_result_dictionary = dict.fromkeys(pair_list)
my_canvas = Canvas()
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
my_scrollbar = Scrollbar(root, orient=tk.VERTICAL, command=my_canvas.yview)
my_scrollbar.pack(side=RIGHT, fill=Y)
my_canvas.configure(yscrollcommand=my_scrollbar.set)
my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all")))
second_frame = Frame(my_canvas)
my_canvas.create_window((0, 0), window=second_frame, anchor="nw")
i = 0
heading_label = Label(second_frame, text="Test Window", font=('Arial',16))
heading_label.grid(column=0, row=0, sticky=tk.NW, columnspan=2, padx=(52, 0), pady=(20, 10))
for pair in pair_list:
sample_scale = tk.Scale(second_frame, from_=9, to=-9, length=600, orient=tk.HORIZONTAL, font=('Arial', 15),
tickinterval=1,resolution=1)
label_left = tk.Label(second_frame, text=pair[0], font=('Arial', 15))
label_left.grid(column=0, row=2 + i, sticky=tk.W, padx=(52, 0), pady=5)
sample_scale.set(((sample_scale['from'] - sample_scale['to']) / 2) + sample_scale['to'])
sample_scale.grid(column=1, row=2 + i, sticky=tk.W, padx=(5, 0), pady=5)
label_right = tk.Label(second_frame, text=pair[1], font=('Arial', 15))
label_right.grid(column=2, row=2 + i, sticky=tk.W, padx=(5, 5), pady=5)
i = i + 100
rectangle_holder_canvas = tk.Canvas(second_frame, width=100, height=70, bd=0, background='#000000')
rectangle_holder_canvas.grid(column=1, row=2, sticky=tk.S, padx=(0, 0), pady=0)
rec = rectangle_holder_canvas.create_rectangle(3, 3, 100, 70, outline='blue', fill='')
rectangle_holder_canvas.tag_raise(rec, 'all')
root.mainloop()
If I use the following code lines, it makes the entire square transparent and will see what's underneath the main window which is not what I want sadly.
root.wm_attributes("-transparentcolor", 'grey')
rectangle_holder_canvas = tk.Canvas(second_frame, width=100, height=70, bd=0, bg="grey")
Appreciate your thoughts and time on how to achieve this.
I read that, "tag_raise" method does not affect canvas window items. To change a window item's stacking order, use a lower or lift method on the window.. So I tried to draw a rectangle on my_canvas by setting second_frame.lower() as shown below code. Then I only see the rectangle but not the scales or labels on the second frame.
my_canvas.create_window((0, 0), window=second_frame.lower(), anchor=CENTER)
rec = my_canvas.create_rectangle(50, 50, 200, 200, outline='blue', fill='blue')
Your question has no easy answer.
The organisation of canvas objects is divided in two groups.
Ordinary graphical objects like rectangle, polygon etc are stacked in the order
of their creation, with the first object in the background and the last object
in the foreground. The stacking order of such objects can be changed via
canvas.lift, canvas.lower, canvas.tag_raise and canvas.tag_lower.
The second group are the canvas window objects, these are created using a
fixed stacking order that ALLWAYS sit above graphical objects.
Therefore it is not possible to place ordinary graphical objects above window
objects.
This would seem to make your objective impossible, however there is (at least)
one solution.
The following code achieves your objective by using a Toplevel window that is
positioned above the canvas. This window uses wm_attributes("-transparentcolor", color)
and overrideredirect(1), it also sets wm_attributes("-topmost", True).
The main window and top window are then bound together via the "Configure"
binding so that moving main window will automatically move top window.
This creates the effect you are looking for, although it may not suit your needs.
I've used one of your Scale objects placed in a canvas window object to simulate
a fragment of your code.
import tkinter as tk
color = "red"
class transParent(tk.Tk):
def __init__(self):
super().__init__()
self.withdraw()
self.columnconfigure(0, weight = 1)
wide, high = 606, 106
self.geometry(f"{wide}x{high}+20+20")
self.canvas = tk.Canvas(
self, background = color, highlightthickness = 0, borderwidth = 0)
self.canvas.grid(sticky = tk.NSEW)
self.s_scale = tk.Scale(
self.canvas, from_ = 9, to = -9, length = 600,
orient = tk.HORIZONTAL, font = "Arial 15",
takefocus = 1, tickinterval = 1, resolution = 1)
self.s_scale.set(0)
self.s_scale.grid(
column = 0, row = 0, sticky = tk.W, padx = 5, pady = 5)
self.sample_window = self.canvas.create_window(
0, 0, window = self.s_scale, anchor = tk.NW)
self.deiconify()
self.wait_visibility()
# build transparency toplevel : width, height, borderwidth
w, h, bw = 100, 100, 4
self.top = tk.Toplevel(
self, padx = 0, pady = 0, background = color,
highlightthickness = 0, relief = "solid", borderwidth = bw)
self.X, self.Y = self.winfo_x, self.winfo_y
self.top.geometry(f"{w}x{h}+{self.X()}+{self.Y()}")
self.top.wm_attributes("-transparentcolor", color)
self.top.overrideredirect(1)
self.top.wm_attributes("-topmost", True)
# estimate top position > trial & error?
self.xx, self.yy = int(wide / 2 - w / 2.4), int(high / 3.4)
# primary bindings
self.bind("<Configure>", self.moveit)
self.top.event_add(
"<<HOOD>>", "<Button-1>", "<Button-2>", "<Button-3>")
self.top.bind("<<HOOD>>", self.focal)
self.focus_force()
def moveit(self, ev):
self.top.geometry(f"+{self.X()+self.xx}+{self.Y()+self.yy}")
self.top.lift()
def focal(self, ev):
self.s_scale.focus_set()
if __name__ == "__main__":
app = transParent()
app.mainloop()
I am making a random number generator and it's like this in the picture.
import random
import time
root = Tk()
root.title("Random Picker V.2")
root.iconbitmap(r'Icon.ico')
canvas = Canvas(root, width=1080, height=720)
canvas.pack()
good = PhotoImage(file='mrwallpapers.png')
goodha = PhotoImage(file='Very good.png')
canvas.create_image(50, 10, image=good)
canvas.create_text(530, 70, fill='white', text='Random Picker V.2', font=("Arial", 40, "underline"))
canvas.create_text(530, 130, fill='white', text='Random Arrow Moves', font=("Arial", 26))
canvas.create_text(530, 700, fill='yellow', text='This was made by Che 1/10 2019', font=("Arial", 15))
item = canvas.create_text(534, 280, fill='white', text='0', font=("Arial", 35))
item1 = canvas.create_text(263, 280, fill='white', text='0', font=("Arial", 35))
item2 = canvas.create_text(800, 280, fill='white', text='0', font=("Arial", 35))
arrow = canvas.create_image(540, 200, image=goodha)
def login():
random1 = random.randint(1, 36)
random2 = random.randint(1, 36)
random3 = random.randint(1, 36)
canvas.itemconfig(item, text=random1)
canvas.itemconfig(item1, text=random2)
canvas.itemconfig(item2, text=random3)
def login1():
random4 = random.randint(1, 45)
random5 = random.randint(1, 45)
random6 = random.randint(1, 45)
canvas.itemconfig(item, text=random4)
canvas.itemconfig(item1, text=random5)
canvas.itemconfig(item2, text=random6)
def login2():
choice = ['260', '-265']
random10 = random.choices(choice)
canvas.move(arrow, random10, 0)
def randomnumber():
canvas.itemconfig(item, fill='blue')
root.after(500, randomnumber)
canvas.itemconfig(item, fill='red')
root.after(500, randomnumber)
gifted = Button(root, font=("Arial", 25), text="Gifted Pick (36)", command=login)
gifted.place(rely=0.59, relx=0.37, relwidth=0.25, relheight=0.07)
normal = Button(root, font=("Arial", 22), text="Normal Pick (45)", command=login1)
normal.place(rely=0.69, relx=0.37, relwidth=0.25, relheight=0.07)
photo = PhotoImage(file='color.png')
spinm = Button(root, image=photo, fg='white', font=("Arial", 22), command=login2)
spinm.place(rely=0.59, relx=0.62, relwidth=0.05, relheight=0.17)
root.mainloop()
I want the canvas image (arrow) moves to left or right or middle randomly with slide animation. Is that possible for it and how do I do it? Because it doesn't work for the code I did (login2) it moves out of the frame and I also want an arrow to slide to left right or middle randomly because it's a random number generator.
I need multiple buttons on a canvas in Python Tkinter. The purpose is to draw connection lines among the buttons. My code:
from tkinter import *
root=Tk()
convas = Canvas(root)
convas.pack()
button1 = Button(text = "button 1")
button1.configure(width = 0, activebackground = "#D2D2D2", relief = GROOVE)
button1_window = convas.create_window(10, 10, anchor=NW, window=button1)
button1.update()
print (button1.winfo_geometry())
button2 = Button(text = "button 2")
button2.configure(width = 0, activebackground = "#D2D2D2", relief = GROOVE)
button2_window = convas.create_window(10, 50, anchor=NW, window=button1)
button2.update()
print (button2.winfo_geometry())
root.mainloop()
running this code, I always just got button 1 in the canvas although I tried to adjust the location in the create_window function, and the anchor=. the button 2 does not show in the canvas at all.
The two prints return:
62x26+10+10
1x1+0+0.
Based on the output 1x1+0+0, the button 2 seems not being rendered. what I am doing wrong?
EDIT:
My mistake:
button2_window = convas.create_window(10, 50, anchor=NW, window=button1)
should be
button2_window = convas.create_window(10, 50, anchor=NW, window=button2)
Your second button code in line 14 says window=button1. Change it to:
button2_window = convas.create_window(10, 50, anchor=NW, window=button2)
So that button2 shows up on its window like this:
I'm trying to understand how bind and events work in python. For example I've created 3 tiles and would like to be able to change the color of one of the tiles but cannot understand or figure out where I'm going wrong. I keep getting:
AttributeError: 'int' object has no attribute 'bind'.
Below is the code and thanks in advance:
import tkinter
def main():
root = tkinter.Tk()
title = tkinter.Label(root, text="Test Window")
title.pack()
canvas= tkinter.Canvas(root, background='green', width = 300, height = 300)
tile1=canvas.create_rectangle(0, 0, 100, 100, fill = 'magenta')
tile2=canvas.create_rectangle(100,0, 200,100, fill = 'blue')
tile3=canvas.create_rectangle(200,0, 300,100, fill = 'blue')
canvas.pack()
def change_square(event):
event.configure(background = 'blue')
tile1.bind("<Button-1>", change_square(tile1))
root.mainloop()
if __name__ == '__main__':
main()
itemconfigure will change the colour:
def main():
root = tkinter.Tk()
title = tkinter.Label(root, text="Test Window")
title.pack()
canvas = tkinter.Canvas(root, background='green', width=300, height=300)
s1 = canvas.create_rectangle(0, 0, 100, 100, fill='magenta')
s2 = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
s3 = canvas.create_rectangle(200, 0, 300, 100, fill='blue')
canvas.pack()
def change_square(event):
canvas.itemconfigure(s1, fill="blue")
canvas.bind("<Button-1>", change_square)
root.mainloop()
If you want to change the middle to black you would use:
canvas.itemconfigure(s2, fill="black")`
And so on.
If you want to change colour based on which you click this should work:
def change_square(event):
x = canvas.canvasx(event.x)
y = canvas.canvasy(event.y)
sq = canvas.find_closest(x,y)[0]
canvas.itemconfigure(sq, fill="black")
canvas.bind("<Button-1>", change_square)
root.mainloop()