Make buttons work on canvas (tkinter) - python

I'm trying to make the buttons on my program to perform an action but I'm not 100% how to do that. I've created the buttons hopefully their correct, but just need some advice on how to make them work ! so when i click the button "add rect" it should add a random rectangle in a random position vice versa for remove.
from tkinter import *
import random
root = Tk()
class Recta:
def __init__(self, height, width):
self.height=60
self.width=80
def randomRects(self,canvas):
w = random.randrange(80)
h = random.randrange(60)
canvas.create_rectangle(0,0,h,w,fill='green')
def create_buttons(self,canvas):
frame = Frame(root, bg='grey', width=400, height=40)
frame.pack(fill='x')
frame = Frame(root, bg='grey', width=400, height=40)
frame.pack(fill='x')
button1 = Button(frame, text='Add Rect')
button1.pack(side='left', padx=10)
button2 = Button(frame, text='Remove Rect')
button2.pack(side='left')
def removeRects(self,canvas):
self.myRect = canvas.create_rectangle(0, 0, w, h, fill='green')
canvas.delete(self.myRect)
c = Canvas(root)
c.pack()
tes = Recta(10,20)
tes.randomRects(c)
tes.create_buttons(1)
root.mainloop()

Your code needed serious reorganization.
Here is something that works to add rectangles. you did not provide a remove rectangle method, so i let you write it - at this moment, the delete button calls randomRect; you likely will need to keep track of the rectangles you create in a collection of some sort in order to be able to remove them.
from tkinter import *
import random
root = Tk()
class Recta:
def __init__(self, height=60, width=80):
self.height = height
self.width = width
self.create_buttons()
self.canvas = Canvas(root)
self.canvas.pack()
def create_buttons(self):
self.frame = Frame(root, bg='grey', width=400, height=40)
self.frame.pack(fill='x')
self.button1 = Button(self.frame, text='Add Rect', command=self.randomRects)
self.button1.pack(side='left', padx=10)
self.button2 = Button(self.frame, text='Remove Rect', command=self.randomRects)
self.button2.pack(side='left')
def randomRects(self):
w = random.randrange(300)
h = random.randrange(200)
self.canvas.create_rectangle(0, 0, w, h, fill='green')
tes = Recta()
root.mainloop()

Related

How to switch between difference "frames"

I have been recently learning how to use tkinter and I wanted to switch between 2 different canvas (whatever term is more appropriate) using buttons. However, whenever I click between the buttons to switch frames the screen doesn't seem to clear. Any way to fix this?
#Imports
import tkinter as tk
#master means the variable
class App(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master.title("Testing") #Setting the title
self.master.minsize(800, 600) #The minimum size it can be
self.canvas = tk.Canvas(self, bg="black")
self.section1()
def section2(self):
self.pack(fill=tk.BOTH, expand=1)
#Creating the canvas and drawing a line
self.canvas.create_line(15, 25, 200, 25, fill="red")
#Going back to the "main menu"
self.exit = tk.Button(self, text="exit", fg="red", command=self.section1)
self.exit.place(x=0, y=50)
self.canvas.pack(fill=tk.BOTH, expand=1)
def section1(self): #Main menu
self.pack(fill=tk.BOTH, expand=1)
self.button = tk.Button(self, text="See Line", fg="red", command=self.section2)
self.button.place(x=0, y=0)
#Exit button
self.exit = tk.Button(self, text="exit", fg="red", command=self.master.destroy)
self.exit.place(x=0, y=25)
window = App() #Declaring the window
window.mainloop()
You can switch between widgets (here canvas, but it could be frames, or buttons, or labels, etc.) using the geometry manager pack-pack_forget (or grid-grid_forget)
Maybe like this:
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("Testing")
self.minsize(800, 600)
self.swap_btn = tk.Button(self, text='swap canvas', command=self.swap_canvas)
self.swap_btn.pack()
self.canvas1 = tk.Canvas(self, bg="black")
self.canvas2 = tk.Canvas(self, bg="blue")
self.canvasses = [self.canvas2, self.canvas1]
self.current_canvas = self.canvas1
self.current_canvas.pack(expand=True, fill=tk.BOTH)
self.draw_some_stuff()
def swap_canvas(self):
self.current_canvas.pack_forget()
self.current_canvas = self.canvasses.pop(0)
self.canvasses.append(self.current_canvas)
self.current_canvas.pack(expand=True, fill=tk.BOTH)
def draw_some_stuff(self):
self.canvas1.create_oval(200, 200, 300, 300, fill='blue')
self.canvas2.create_rectangle(200, 200, 300, 300, fill='black')
self.canvas1.create_oval(400, 200, 500, 300, fill='blue')
self.canvas2.create_rectangle(400, 200, 500, 300, fill='black')
window = App() #Declaring the window
window.mainloop()

tkinter canvas text output

I have been looking at my code for a while and new to tkinter. The purpose of my code is to display text within the Canvas widget not overlay a label. But unsure how to do this:
My code is as follows:
from tkinter import *
class Example(Frame):
def printLabel(self):
self.hello = []
self.hello.append('Hello')
self.hello.append('World!')
return(self.hello)
def updatePanel(self):
self.panelA.config(text="{}".format(self.printLabel()))
def __init__(self, root):
Frame.__init__(self, root)
self.buttonA()
self.viewingPanel()
def buttonA(self):
self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height = 11, width = 13, command=lambda: self.updatePanel())
self.firstPage.place(x=0, y=0)
def viewingPanel(self):
self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3, anchor=NW, text="")
self.panelA.place(x=100, y=0)
self.cl= Canvas(self.panelA,bg='WHITE',width=165,height=113,relief=SUNKEN)
canvas_id = self.cl.create_text(15, 15, anchor="nw")
self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
self.xb.pack(side=BOTTOM,fill=X)
self.xb.config(command=self.cl.xview)
self.yb= Scrollbar(self.panelA,orient="vertical", command=self.cl.yview)
self.yb.pack(side=RIGHT,fill=Y)
self.yb.config(command=self.cl.yview)
self.cl.itemconfig(canvas_id,font=('Consolas',9), text="{}".format(self.printLabel()))
self.cl.configure(scrollregion = self.cl.bbox("all"))
self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
self.cl.config(width=250,height=150)
self.cl.pack(side=LEFT,expand=True,fill=BOTH)
def main():
root = Tk()
root.title("Tk")
root.geometry('378x176')
app = Example(root)
app.pack(expand=True, fill=BOTH)
root.mainloop()
if __name__ == '__main__':
main()
The Hello World! should display without the brackets in the Canvas but the main issue is that when I click on the Button it just overlaps the canvas and prints out the append on to the Label.
The Label should be inside the Canvas.
Here's how to fix the "main issue" along with the "brackets issue". The latter is taken care of by using the string join() method as suggested in the comments.
The updatePanel() method has been modified so it first create a Label widget with the text you want displayed in it, followed by a Canvas "window" object specifying that widget as its contents. Code for the way you were attempting to do it was also removed from the other class methods.
from tkinter import *
class Example(Frame):
def __init__(self, root):
Frame.__init__(self, root)
self.buttonA()
self.viewingPanel()
def printLabel(self):
text = []
text.append('Hello')
text.append('World!')
return ' '.join(text)
def updatePanel(self):
label = Label(self, bg='white', padx=3, pady=3, anchor=NW,
text=self.printLabel())
label.place(relx=0.5, rely=0.5, anchor=CENTER)
self.cl.create_window(100, 100, window=label) # Put Label in a Canvas "window".
def buttonA(self):
self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height=11,
width=13, command=lambda: self.updatePanel())
self.firstPage.place(x=0, y=0)
def viewingPanel(self):
self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3,
anchor=NW, text="")
self.panelA.place(x=100, y=0)
self.cl= Canvas(self.panelA, bg='WHITE', width=165, height=113, relief=SUNKEN)
canvas_id = self.cl.create_text(15, 15, anchor="nw")
self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
self.xb.pack(side=BOTTOM, fill=X)
self.xb.config(command=self.cl.xview)
self.yb= Scrollbar(self.panelA, orient="vertical", command=self.cl.yview)
self.yb.pack(side=RIGHT, fill=Y)
self.yb.config(command=self.cl.yview)
self.cl.itemconfig(canvas_id, font=('Consolas',9), text=self.printLabel())
self.cl.configure(scrollregion=self.cl.bbox("all"))
self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
self.cl.config(width=250, height=150)
self.cl.pack(side=LEFT, expand=True, fill=BOTH)
def main():
root = Tk()
root.title("Tk")
root.geometry('378x176')
app = Example(root)
app.pack(expand=True, fill=BOTH)
root.mainloop()
if __name__ == '__main__':
main()

Scrollbar, Checkbutton and canvas in python 2.7

I try to open a new window where there will be a list of check box and will be scrollable.
But, my list is not scrolled.
this is my code:
class PageCanvas1(tk.Toplevel):
def __init__(self, parent):
global arr
global users
arr = {}
tk.Toplevel.__init__(self, parent)
self.title('Canvas')
self.geometry('400x600')
canvas = tk.Canvas(self, bg='white', scrollregion=(0, 0, 400, 20000))
canvas.pack(fill='both', expand=True)
vbar = tk.Scrollbar(canvas, orient='vertical')
vbar.pack(side='right', fill='y')
vbar.config(command=canvas.yview)
canvas.config(yscrollcommand=vbar.set)
canvas.create_text(5, 0, anchor='nw', text="Choose users: ")
for i in range(1000):
arr[i] = tk.IntVar()
Checkbutton(canvas, text=str(i), variable=arr[i]).pack()#.grid(row=i, sticky=W)
root = Tk()
b_choose = Button(root, text='choose users', height=3, width=15, bg="turquoise", command=(lambda arr=ents: PageCanvas(root)))
I can not find any answer to this specific thing, that a new window must be opened! I would be happy to help!
import Tkinter as tk
class PageCanvas1(tk.Toplevel):
def __init__(self, parent):
global arr # why use global? set it as an attribute?
global users # same as above?
arr = {}
tk.Toplevel.__init__(self, parent)
self.title('Canvas')
self.geometry('400x600')
canvas = tk.Canvas(self, bg='white', scrollregion=(0, 0, 400, 20000))
canvas.pack(fill='both', expand=True)
vbar = tk.Scrollbar(canvas, orient='vertical')
vbar.pack(side='right', fill='y')
vbar.config(command=canvas.yview)
canvas.config(yscrollcommand=vbar.set)
canvas.create_text(5, 0, anchor='nw', text="Choose users: ")
# we need a container widget to put into the canvas
f = tk.Frame(canvas)
# you need to create a window into the canvas for the widget to scroll
canvas.create_window((200, 0), window=f, anchor="n")
for i in range(0, 1000):
arr[i] = tk.IntVar()
# widget must be packed into the container, not the canvas
tk.Checkbutton(f, text=str(i), variable=arr[i]).pack()#.grid(row=i, sticky=W)
if __name__ == "__main__":
app = PageCanvas1(None)
app.mainloop()
You can only scroll objects in a canvas if they are added to the canvas via the create_window method, and not with grid, pack, or place.

delete method on canvas tkinter

Trying to delete a random shape on canvas by clicking the "remove rect" button created. but my method doesn't seem to work. I keep getting this error, must be small but I can't seem to find it.
TypeError: removeRects() missing 1 required positional argument: 'canvas'
from tkinter import *
import random
root = Tk()
class Recta:
def __init__(self, height=60, width=80):
self.height = height
self.width = width
self.create_buttons()
self.canvas = Canvas(root)
self.canvas.pack()
def removeRects(self,canvas):
my_rect = self.canvas.create_rectangle(0,0,w,h,fill = "green")
self.canvas.delete(my_rect)
def create_buttons(self):
self.frame = Frame(root, bg='grey', width=400, height=40)
self.frame.pack(fill='x')
self.button1 = Button(self.frame, text='Rect', command=self.randomRects)
self.button1.pack(side='left', padx=10)
self.button2 = Button(self.frame, text='Remove Rect', command=self.removeRects)
self.button2.pack(side='left')
def randomRects(self):
w = random.randrange(300)
h = random.randrange(200)
self.canvas.create_rectangle(0, 0, w, h, fill= "green")
tes = Recta()
root.mainloop()
You have to keep track of the rectangles you are creating in a collection; then extract the id from the collection in order to remove a rectangle.
here, I created a list to aggregate the ids of the rectangle created: self.canvas.create_rectangle(0, 0, w, h, fill='green') returns an id number that is stored in the collection.
Upon calling the delete method, the id from the last created rectangle is retrieved (and removed from the collection) and used to remove the rectangle from the canvas.
import tkinter as tk
import random
root = tk.Tk()
class Recta:
def __init__(self, height=60, width=80):
self.height = height
self.width = width
self.create_buttons()
self.canvas = tk.Canvas(root)
self.canvas.pack()
self.rects = []
def create_buttons(self):
self.frame = tk.Frame(root, bg='grey', width=400, height=40)
self.frame.pack(fill='x')
self.button1 = tk.Button(self.frame, text='Add Rect', command=self.randomRects)
self.button1.pack(side='left', padx=10)
self.button2 = tk.Button(self.frame, text='Remove Rect', command=self.removeRects)
self.button2.pack(side='left')
def removeRects(self):
if len(self.rects) > 0:
self.canvas.delete(self.rects.pop())
def randomRects(self):
w = random.randrange(300)
h = random.randrange(200)
self.rects.append(self.canvas.create_rectangle(0, 0, w, h, fill='green'))
tes = Recta()
root.mainloop()
Here is the same code with a * import!
from tkinter import *
import random
root = Tk()
class Recta:
def __init__(self, height=60, width=80):
self.height = height
self.width = width
self.create_buttons()
self.canvas = Canvas(root)
self.canvas.pack()
self.rects = []
def create_buttons(self):
self.frame = Frame(root, bg='grey', width=400, height=40)
self.frame.pack(fill='x')
self.button1 = Button(self.frame, text='Add Rect', command=self.randomRects)
self.button1.pack(side='left', padx=10)
self.button2 = Button(self.frame, text='Remove Rect', command=self.removeRects)
self.button2.pack(side='left')
def removeRects(self):
if len(self.rects) > 0:
self.canvas.delete(self.rects.pop())
def randomRects(self):
w = random.randrange(300)
h = random.randrange(200)
self.rects.append(self.canvas.create_rectangle(0, 0, w, h, fill='green'))
tes = Recta()
root.mainloop()

Image behind buttons in tkinter (PhotoImage)

I've been trying to add an image so that my buttons sit on top of the image, but have only been able to make the image cover everything completely or force the image to be underneath the horizontal part the buttons cover.
Here is the relevant code for it:
class MainMenu(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.master = master
self.initUI()
def initUI(self):
self.master.title("Adventure")
bg = PhotoImage(file="Background-gif.gif")
newGameButton = Button(self, text="New Game", height=2, width=20, command=self.newGame)
newGameButton.pack(side=TOP, pady=50)
loadGameButton = Button(self, text="Load Game", height=2, width=20, command=self.loadGame)
loadGameButton.pack(side=TOP)
quitButton = Button(self, text="Quit", height=2, width=20, command=self.close)
quitButton.pack(side=TOP, pady=50)
label = Label(self, image=bg)
label.image = bg
label.pack(fill=BOTH, expand=1)
self.pack()
Many thanks.
You could place an image on a canvas, and then place a button on the canvas:
import Tkinter as tk
import ImageTk
FILENAME = 'image.png'
root = tk.Tk()
canvas = tk.Canvas(root, width=250, height=250)
canvas.pack()
tk_img = ImageTk.PhotoImage(file = FILENAME)
canvas.create_image(125, 125, image=tk_img)
quit_button = tk.Button(root, text = "Quit", command = root.quit, anchor = 'w',
width = 10, activebackground = "#33B5E5")
quit_button_window = canvas.create_window(10, 10, anchor='nw', window=quit_button)
root.mainloop()

Categories

Resources