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()
Related
I am trying to draw a image on a canvas in my tkinter gui. But when I draw text it is displayed I was wondering why it does not display and how I can fix it?
import tkMessageBox, PIL.ImageTk, PIL.Image, socket, queue, ttk
from threading import Thread
from Tkinter import *
class GUI(Frame):
def __init__(self, parent):
Frame.__init__(self,parent)
self.pack()
def main(self):
self.bBar = Frame(self, bg="#3A3A3C", bd=0)
self.bBar.place(x=0, y=450, width=700, height=600)
self.can = Canvas(self.bBar, width=700, height=50, highlightthickness=0, bg="red", bd=0)
img = PIL.ImageTk.PhotoImage(PIL.Image.open("Images/uBar.png"))
self.can.pack()
self.can.create_text(100, 10, text="My Text")
self.can.create_image(10,10, image=img, anchor=NW)
if "__Main__":
root = Tk()
root.title("Frozen Cloud")
root.geometry("700x500")
root.config(background="White")
root.resizable(0,0)
root.iconbitmap("Images/Icon.ico")
gui = GUI(root)
#gui.splashSc()
gui.mScreen()
root.mainloop()
Try this, you have used self but not defined within a function, also root = tk() should be at the start.
root = Tk()
def main(self):
self.bBar = Frame(self, bg="#3A3A3C", bd=0)
self.bBar.place(x=0, y=450, width=700, height=600)
self.can = Canvas(self.bBar, width=700, height=50, highlightthickness=0, bg="red", bd=0)
img = PIL.ImageTk.PhotoImage(PIL.Image.open("Images/uBar.png"))
self.can.pack()
self.can.create_text(100, 10, text="My Text")
self.can.create_image(10,10, image=img, anchor=NW)
if "__Main__":
root.title("Frozen Cloud")
root.geometry("700x500")
root.config(background="White")
root.resizable(0,0)
root.iconbitmap("iImages/Icon.co")
gui = GUI(root)
#gui.splashSc()
gui.mScreen()
root.mainloop()
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.
I have a problem regarding the layout in tkinter. This is the
Layout I want to have and this is whatI have right now.
I am not understanding why this is happening. I thought when I specify the width and height for a specific frame it would take all this place but this is not happening looking at self.GameStatFrame. It would be nice if someone could explain to me why code does what it does and what my mistakes were.
Here is the code:
class Application(tk.Frame):
def __init__(self, parent):
self.parent = parent
tk.Frame.__init__(self, parent)
#self.update_idletasks()
self.createWidgets()
def createWidgets(self):
#new frame for everything not in the canvas
#self.Frame = tk.Frame(self.parent)
self.MlGameStatFrame = tk.Frame(self.parent, width=600, height=300,
bg='blue')
self.GameStatFrame = tk.Frame(self.MlGameStatFrame, bg='white',
width=300, height=300)
self.MlFrame = tk.Frame(self.MlGameStatFrame, bg='white',
width=300, height=300)
#self.Frame.pack()
self.createGraphWidget()
self.MlGameStatFrame.pack()
self.GameStatFrame.pack(side=tk.LEFT, anchor=tk.W, fill=tk.BOTH)
self.MlFrame.pack(side=tk.BOTTOM, fill=tk.BOTH)
self.createGameStats(self.GameStatFrame)
self.createMlStats(self.MlFrame)
#self.createLog()
def createGraphWidget(self):
self.graph = tk.Canvas(self.parent, background ='white',
width=200,height=300)
self.graph.create_rectangle(0,20,40,50)
self.graph.pack(side=tk.TOP,fill=tk.X)
# needs to get a frame because side by side with Ml stats
def createGameStats(self,GameFrame):
Frame1 = tk.Frame(GameFrame, bg='red', width=300)
tk.Label(Frame1, text="Status: ").pack(side=tk.LEFT, expand=tk.YES)
#initialize with certain value for now
self.statusChange = tk.Label(Frame1,
text="Learning").pack(side=tk.LEFT, expand=tk.YES)
Frame2=tk.Frame(GameFrame, bg='green')
tk.Label(Frame2, text="Fitness").pack(side=tk.LEFT, expand=tk.YES,
anchor=tk.W) #could get changed
self.fitnessChange = tk.Label(Frame2, text="6").pack(side=tk.LEFT,
expand=tk.YES)
Frame1.pack(side=tk.TOP, anchor=tk.W)
Frame2.pack(side=tk.TOP,fill=tk.X, anchor=tk.W)
def createMlStats(self, MlFrame):
Frame1 = tk.Frame(MlFrame)
tk.Label(Frame1, text="Status: ").pack(side=tk.LEFT, expand=tk.YES)
# initialize with certain value for now
self.statusChange = tk.Label(Frame1,
text="Learning").pack(side=tk.LEFT, fill=tk.X, expand=tk.YES)
Frame2=tk.Frame(MlFrame)
tk.Label(Frame2, text="Fitness").pack(expand=tk.YES, anchor=tk.W)
self.fitnessChange = tk.Label(Frame2, text="6").pack(side=tk.LEFT,
fill=tk.X, expand=tk.YES)
Frame1.pack(side=tk.TOP, fill=tk.BOTH,anchor=tk.W)
Frame2.pack(side=tk.TOP,fill=tk.BOTH)
def main():
root = tk.Tk()
root.geometry('600x900-0+0') #120* 50 ppixels in top right corner of desktop
app = Application(root)
app.master.title('Sample application')
app.mainloop()
if __name__ == '__main__':
main()
The .grid layout manager is much more flexible:
class Application(Frame):
def __init__(self, parent):
self.parent = parent
Frame.__init__(self, parent)
self.create_widgets()
def create_widgets(self):
graph = Canvas(self.parent, width=200, height=300, bg="white")
graph.create_rectangle(0, 20, 40, 50)
mlgamestat_frame = Frame(self.parent, width=600, height=300, bg="blue")
gamestat_frame = Frame(mlgamestat_frame, width=300, height=300, bg="yellow")
ml_frame = Frame(mlgamestat_frame, width=300, height=300, bg="green")
graph.grid(row=0, column=0)
mlgamestat_frame.grid(row=1, column=0)
gamestat_frame.grid(row=0, column=0)
ml_frame.grid(row=0, column=1)
You can place widgets as if they were in a table. The code above makes your intended layout.
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()
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()