How to detect keyboard press in python window? - python

from tkinter import *
root = Tk()
root.title('FAS')
root.geometry("600x650")
#root.attributes('-alpha', 0.5)
root.wm_attributes("-topmost", True)
root.lift()
root.wm_attributes("-transparentcolor", "grey")
#background image
bg = PhotoImage(file="3MtoCW.png")
#this is to make the background image transparents
red_frame = Frame(root, width=600, height=650, bg='grey')
red_frame.place(x=0, y=0)
my_label = Label(root, image=bg, bg='grey')
my_label.place(x=0, y=0)
root.mainloop()
I want that when I press a key in the tkinter window, the original background image "3MtoCW.png" will swap to a new background image called "3MswCW.png"
How can I do that?

You need to create a function that would change the Label's configuration on keypress and bind this function to the Event
The below should do the trick
from tkinter import *
root = Tk()
root.title('FAS')
root.geometry("600x650")
# root.attributes('-alpha', 0.5)
root.wm_attributes("-topmost", True)
root.lift()
root.wm_attributes("-transparentcolor", "grey")
bg_images = ["3MtoCW.jpg", "3MswCW.jpg"]
idx = 0
# background image
bg = PhotoImage(file="3MtoCW.png")
red_frame = Frame(root, width=600, height=650, bg='red')
red_frame.place(x=0, y=0)
my_label = Label(root, image=bg, bg='grey')
my_label.place(x=0, y=0)
def keypress(e):
print("called")
global idx
idx = (idx + 1) % 2
my_label.config(image=PhotoImage(file=bg_images[idx]))
red_frame.bind("<KeyPress>", keypress)
red_frame.pack()
red_frame.focus_set()
root.mainloop()

You want to bind an event to root. Here's a list of events you can "look" for
https://www.python-course.eu/tkinter_events_binds.php
bg = PhotoImage(file="3MtoCW.png")
root.bind('<KeyPress>', lambda: bg.configure(file="3MswCW.png")
or instead of using lambda, you can do this in a new function. Make sure to omit brackets when you bind the event or it will call the function instead of pointing to it.
def changeimage(event=None):
bg.configure(file="3MswCW.png")
root.bind('<KeyPress>', changeimage)

Related

Why isn't this frame in tkinter centered correctly?

I want this entry bar and other contents I'll add to the frame later to be centred correctly, I received this code that supposedly should work but it isn't.
import tkinter as tk
import math
import time
root = tk.Tk()
root.geometry()
root.attributes("-fullscreen", True)
exit_button = tk.Button(root, text = "Exit", command = root.destroy)
exit_button.place(x=1506, y=0)
frame = tk.Frame(root)
main_entry = tk.Entry(root, width = 100, fg = "black")
main_entry.place(x=50, y=50)
frame.place(relx=.5,rely=.5, anchor='center')
root.mainloop()
As you can see the frame isn't centred so how can I fix this?
In order to achieve widget centering on a fullscreen I've had to use grid manager.
The code below works but the exact positioning requires some fiddling with frame padding.
frame padx = w/2-300 and pady = h/2-45 are arbitrary values found using a bit of trial and error.
import tkinter as tk
root = tk.Tk()
root.attributes( '-fullscreen', True )
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
frame = tk.Frame( root )
main_entry = tk.Entry( frame, width = 100 )
main_entry.grid( row = 0, column = 0, sticky = tk.NSEW )
frame.grid( row = 0, column = 0, padx = w/2-300, pady = h/2-45, sticky = tk.NSEW )
exit_button = tk.Button( frame, text = 'Exit', command = root.destroy )
exit_button.grid( row = 1, column = 0, sticky = tk.NSEW )
tk.mainloop()
Frame automatically changes size to size of objects inside Frame (when you use pack()) but you have nothing inside Frame. You put all widgets directly in root - so Frame has no size (width zero, height zero) and it is not visible.
When I use tk.Frame(root, bg='red', width=100, height=100) then I see small red frame in the center.
You have two problems:
(1) you put Entry in wrong parent - it has to be frame instead of root,
(2) you use place() which doesn't resize Frame to its children and it has size zero - so you don't see it. You would have to set size of Frame manully (ie. tk.Frame(..., width=100, height=100)) or you could use pack() and it will resize it automatically.
I add colors for backgrounds to see widgets. blue for window and red for frame.
import tkinter as tk
root = tk.Tk()
root['bg'] = 'blue'
root.attributes("-fullscreen", True)
exit_button = tk.Button(root, text="Exit", command=root.destroy)
exit_button.place(x=1506, y=0)
frame = tk.Frame(root, bg='red')
frame.place(relx=.5, rely=.5, anchor='center')
main_entry = tk.Entry(frame, width=100, fg="black")
main_entry.pack(padx=50, pady=50) # with external margins 50
root.mainloop()

How to get the buttons to the left side?

I am trying to create the buttons using tkinter.
Here is my code
import tkinter as tk
def pressed():
print("button pressed!")
def create_layout(frame):
frame.pack(fill=None,expand=True)
mycolor = '#%02x%02x%02x' % (250, 250, 210)
root.configure(bg=mycolor)
bottomframe = tk.Frame(root)
bottomframe.pack( side = tk.LEFT )
button1 = tk.Button(frame, text="Button1", fg="black",command=pressed,anchor="w")
button1.pack( side = tk.LEFT)
button2 =tk.Button(frame, text="Button2", fg="black",command=pressed,anchor="w")
button2.pack( side = tk.LEFT )
root = tk.Tk()
root.geometry("250x150")
frame = tk.Frame(root)
create_layout(frame)
root.mainloop()
I have specified the anchor="w", and side="LEFT", but it does not seem to be work.
Output of the code:
Changing frame.pack(fill=None,expand=True) to frame.pack(fill=None,expand=True, anchor="w") will align the buttons to the left side.

Python canvas colour change by button

I am a python self learner. I was stuck on some practice.
My idea was to create a pop out GUI with buttons that can change the canvas colour.
from Tkinter import *
import ttk
import tkMessageBox
root = Tk()
root.title("Colour!")
canvasColor = "yellow"
def buttonRed() :
canvas = Canvas(root, bg = "red", height=100, width=100)
canvas.grid(row=0,column=2)
button = ttk.Button(root, text="Red", command = buttonRed)
button.grid(row=2,column=1)
button2 = ttk.Button(root, text ="Green", command = buttonGreen)
button2.grid(row=2,column=2)
button3 = ttk.Button(root, text="Blue", command = buttonBlue)
button3.grid(row=2,column=3)
canvas = Canvas(root, bg = canvasColor, height=200, width=200)
canvas.grid(row=0,column=2)
root.configure(background='white')
root.mainloop()
i haven't put in the green and blue button command yet, but instead of creating a new canvas when the colour button clicked, i just wanted to have the default canvas colour change.
Any help will be much appreciated!
Thanks in advance.
I think this is what you need -
from Tkinter import *
import ttk
import tkMessageBox
root = Tk()
root.title("Colour!")
canvasColor = "yellow"
def buttonRed() :
canvas.config(background="red")
def buttonGreen() :
canvas.config(background="green")
def buttonBlue() :
canvas.config(background="blue")
button = ttk.Button(root, text="Red", command = buttonRed)
button.grid(row=2,column=1)
button2 = ttk.Button(root, text ="Green", command = buttonGreen)
button2.grid(row=2,column=2)
button3 = ttk.Button(root, text="Blue", command = buttonBlue)
button3.grid(row=2,column=3)
canvas = Canvas(root, bg = canvasColor, height=200, width=200)
canvas.grid(row=0,column=2)
#canvas.config(background="black")
root.configure(background='white')
root.mainloop()

How to make image disappear in tkinter

I've been programming a random operator name generator for Rainbox Six Siege and I want the operators picture to appear when their name comes up. The image appears fine, but it won't go away. This is my Code:
from tkinter import *
import tkinter
import random
names = ['Sledge','Thatcher','Ash','Thermite','Twitch','Montagne','Glaz','Fuze','Blitz','IQ','Buck','Blackbeard','Capitão','Hibana']
name = ["Smoke","Mute","Castle","Pulse","Doc","Rook","Kapkan","Tachanka","Jäger","Bandit","Frost","Valkyrie","Caveira","Echo"]
root = tkinter.Tk()
def pickName():
rad = random.choice(names)
photo = PhotoImage(file=rad+".png")
label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()
nameLabel.configure(text=rad, foreground="white", background="blue")
root.configure(background='blue')
def pickName1(): nameLabel.configure(text=random.choice(name),background="orange",foreground="black")
root.configure(background='orange')
root.title("Operator Picker")
root.geometry("250x100")
nameLabel = tkinter.Label(root, text="", font=('Helvetica', 32))
nameLabel.pack()
Grid()
f1 = tkinter.Frame(root, height=100, width=100) #defines frame size in
pixels
f1.pack(side=tkinter.LEFT) #packs on the left
f1.pack_propagate(0) #tells frame not to let children control size
pickButton1 = tkinter.Button(f1, command=pickName, text="Pick
Attack",background="blue",foreground="white")
pickButton1.pack(fill=tkinter.BOTH, expand=1) #takes up all available space
f2 = tkinter.Frame(root, height=100, width=100)
f2.pack(side=tkinter.RIGHT)
f2.pack_propagate(0)
pickButton2 = tkinter.Button(f2, command=pickName1, text="Pick
Defend",background="orange",foreground="black")
pickButton2.pack(fill=tkinter.BOTH, expand=1)
root.mainloop()
Note: This is still a WIP, all I need is to know how to get rid of the pictures once they appear. This is what it looks like when more than one image appears: https://imgur.com/eroXLLn
You are adding a new Label every time you call that function. Instead, you should make the Label only once (probably in the initialization stage), and update the picture. Just like you update the text for nameLabel, plus the step to keep the reference.
photo_label = tkinter.Label()
def pickName():
rad = random.choice(names)
photo = PhotoImage(file=rad+".png")
photo_label.configure(image = photo)
photo_label.image = photo # keep a reference!
photo_label.pack()
nameLabel.configure(text=rad, foreground="white", background="blue")
and your whole code should look like:
from tkinter import *
import tkinter
import random
names = ['Sledge','Thatcher','Ash','Thermite','Twitch','Montagne','Glaz','Fuze','Blitz','IQ','Buck','Blackbeard','Capitão','Hibana']
name = ["Smoke","Mute","Castle","Pulse","Doc","Rook","Kapkan","Tachanka","Jäger","Bandit","Frost","Valkyrie","Caveira","Echo"]
root = tkinter.Tk()
photo_label = tkinter.Label()
def pickName():
rad = random.choice(names)
photo = PhotoImage(file=rad+".png")
photo_label.configure(image = photo)
photo_label.image = photo # keep a reference!
photo_label.pack()
nameLabel.configure(text=rad, foreground="white", background="blue")
root.configure(background='blue')
def pickName1(): nameLabel.configure(text=random.choice(name),background="orange",foreground="black")
root.configure(background='orange')
root.title("Operator Picker")
root.geometry("250x100")
nameLabel = tkinter.Label(root, text="", font=('Helvetica', 32))
nameLabel.pack()
Grid()
f1 = tkinter.Frame(root, height=100, width=100) #defines frame size inpixels
f1.pack(side=tkinter.LEFT) #packs on the left
f1.pack_propagate(0) #tells frame not to let children control size
pickButton1 = tkinter.Button(f1, command=pickName, text="PickAttack",background="blue",foreground="white")
pickButton1.pack(fill=tkinter.BOTH, expand=1) #takes up all available space
f2 = tkinter.Frame(root, height=100, width=100)
f2.pack(side=tkinter.RIGHT)
f2.pack_propagate(0)
pickButton2 = tkinter.Button(f2, command=pickName1, text="PickDefend",background="orange",foreground="black")
pickButton2.pack(fill=tkinter.BOTH, expand=1)
root.mainloop()

Python tkinter grid layout problems

I'm creating a very simple UI using Tkinter and python, but I'm having trouble sizing GUI elements and using the grid format to place them correctly. Here's a first-order approximation of what I'm trying to have:
Here's the code I have so far. I keep getting close, but I don't think I really understand what I'm doing. Any help is much appreciated!
#User interface
root = Tk()
window_width = root.winfo_screenwidth()
window_height = root.winfo_screenheight()
root.geometry ("%dx%d"%(window_width,window_height))
menu_bar = Menu(root)
menu = Menu(menu_bar, tearoff=0)
menu.add_command(label="Open", command = open_file)
menu.add_command(label="Save", command = save)
menu.add_separator()
menu.add_command(label="Quit", command = exit)
menu_bar.add_cascade(label="File",menu=menu)
root.config(menu=menu_bar)
#textbox is the window in which the code is written
textbox = Text(root, width=50, height = window_height/20+4)
#canvas is where the car will go
canvas_frame= Frame(root, width = window_width/1.5, height = window_height-200)
canvas_frame.configure(borderwidth=1.5,background='black')
canvas = Canvas(canvas_frame, width = window_width/1.5, height = window_height-200)
#console to print to
console = Text(root, width = int(window_width/1.5), height = 10)
run_button = Button(root, text = "Run", command = lambda:generate_program(textbox.get(1.0,END)))
clear_button = Button(root, text = "Clear text", command = clear)
#add them to frame
textbox.grid(row=0, column=0, rowspan=20, columnspan=10)
run_button.grid(row=21,column=0)
clear_button.grid(row=21,column=1)
canvas_frame.grid(row=0,rowspan=10,column=21,columnspan=25)
canvas.grid(row=0, rowspan=1, column=21, columnspan=25)
console.grid(row = 1, rowspan=1, column = 21, columnspan=25)
root.mainloop()
In my opinion, this is layout can be much easier with the pack geometry manager. One of the problems is that you are trying to make the width and the height of each widget fit in its place with rowspan and columspan options. Also, since canvasis inside a frame, you have to think that it is like inside a new window, so a simple call to canvas.grid() would be enough.
However, with pack() you just have to put textbox, run_button and clear_button inside a new frame:
left_frame = Frame(root)
textbox = Text(left_frame, ...)
run_button = Button(left_frame, ...)
clear_button = Button(left_frame, ...)
canvas_frame= Frame(root, ...)
canvas_frame.configure(borderwidth=1.5,background='black')
canvas = Canvas(canvas_frame, ...)
console = Text(root, ...)
left_frame.pack(side=LEFT)
textbox.pack()
run_button.pack(side=LEFT)
clear_button.pack()
canvas_frame.pack()
canvas.pack()
console.pack()

Categories

Resources