I'm quite new to Tkinter and this is my first program, can anyone tell me why the canvas is not showing up? I'm not getting any errors so I assume it is working but just not visible? I tried moving it up a layer but it was still invisible. Here is my code:
from Tkinter import *
import Tkinter as tk
class Application(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.frame = Frame(self.master)
self.master = master
self.window()
self.drawFigure()
# self.master.attributes('-fullscreen', True)
self.master.bind("<Escape>", self.end_fullscreen)
def window(self):
self.frame = Frame(self.master)
screen_width = self.frame.winfo_screenwidth() / 2
screen_height = self.frame.winfo_screenheight() / 2
self.master.geometry('%dx%d' % (screen_width, screen_height))
def end_fullscreen(self, event=None):
self.master.attributes("-fullscreen", False)
def drawFigure(self):
self.frame = Frame(self.master)
self.C = Canvas(self.frame, width=200, height=200, bg = 'red')
self.C.pack()
self.C.create_rectangle(50, 20, 150, 80, fill="#476042")
if __name__ == '__main__':
root = tk.Tk()
w = Application(root)
w.master.mainloop()
Appreciate all the input.
You import Tkinter and Tkinter as tk, which gets confusing.
Application inherits from Frame so you don't have to create additional frames inside. Certainly not more than one named self.frame.
How about this:
from Tkinter import *
class Application(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.master = master
self.pack()
self.window()
self.drawFigure()
self.master.bind("<Escape>", self.end_fullscreen)
def window(self):
screen_width = self.winfo_screenwidth() / 2
screen_height = self.winfo_screenheight() / 2
self.master.geometry('%dx%d' % (screen_width, screen_height))
def end_fullscreen(self, event=None):
self.master.attributes("-fullscreen", False)
def drawFigure(self):
self.C = Canvas(self, width=200, height=200, bg = 'red')
self.C.pack()
self.C.create_rectangle(50, 20, 150, 80, fill="#476042")
if __name__ == '__main__':
root = Tk()
w = Application(root)
w.master.mainloop()
You forgot to call pack() on the Frame you created in drawFigure():
def drawFigure(self):
self.frame = Frame(self.master)
self.frame.pack() # <--- There
self.C = Canvas(self.frame, width=200, height=200, bg = 'red')
self.C.pack()
self.C.create_rectangle(50, 20, 150, 80, fill="#476042")
You’re creating three sub frames of your parent, storing each of them as self.frame (so all but the last one are lost), and not placing any of them anywhere.
So, you’ve correctly placed the canvas on one of these invisible frames, but that doesn’t do any good.
I’m not sure what you’re trying to do with all these separate frames.
If you really need three sibling frames, you have to store them in separate variables, or in a list, or something, and you need to place them.
If you need one sibling frame, just create it once instead of three times, and again, you need to place it.
If you need three or one child frames instead of sibling frames, create them with self rather than self.master.
If you don’t need any sibling or child frames at all, don’t create them, and just place the canvas on self instead of self.frame.
Related
I want to have two tkinter windows. A button should be in the first window, and a reaction text should be in the second window.
My questions:
Must the second window have no modal?
How do I make the second window movable?
How can I give information to second window via callback function?
Thanks in advance for answers and advice!
Here is some code that may help you:
from tkinter import *
class App:
def __init__(self):
self.window1 = Tk()
self.window2 = Toplevel()
self.button = Button(self.window1, bd = 5, text = "Click Me!", command = self.update)
self.button.pack()
self.label = Label(self.window2, bd = 5, text = "Button has not been clicked.")
self.label.pack()
def update(self):
self.label.config(text = "Button has been clicked!")
self.window2.update()
app = App()
Explanation:
The first line imports tkinter
In the next line, we create a class. At the bottom of the code, we create an object using that class. This is useful because when the object is created, the functions in the class are already defined, so the function definition can be after when it is called.
After we declare our class, in __init__, we write code that will run when an object is created from that class. The code creates two windows. One contains a button, and the other one contains a label. The button has a command parameter to run the class function, update.
In update, we change the label text and update the window.
I have not next questions. My problems solution is here:
import tkinter as tk
class ViewOnMoon(tk.Toplevel):
def __init__(self, parent = None, draw = None):
tk.Toplevel.__init__(self, parent)
self.transient(parent)
self.title('View')
self.minsize(height = 300, width = 300)
fr_canvas = tk.Frame(self)
fr_canvas.place(relx=0.23, rely=0.01, anchor="nw")
self.canv_w = 200
self.canv_h = 200
self.canvas = tk.Canvas(fr_canvas, bg='white', width = self.canv_w, height=self.canv_h)
self.canvas.grid(column = 0, row = 0)
return
class GuiMoonMove(tk.Frame):
def __init__(self, master):
mon_h = 600
mon_w = 1250
tk.Frame.__init__(self, master)
self.frame = tk.Frame(master, width=1000, height=200, bd=2)
self.master.title('Move')
self.master.minsize(height = mon_h, width = mon_w)
fr_canvas = tk.Frame(self.master)
fr_canvas.place(relx=0.23, rely=0.01, anchor="nw")
fr_button = tk.Frame(self.master)
fr_button.place(relx=0.02, rely=0.06, anchor="nw")
self.canv_h = 600
self.canv_w = 950
self.lbl_view = tk.BooleanVar()
chb_view_on_moon = tk.Checkbutton(fr_button, text="Pohled na Měsíc", variable = self.lbl_view, \
onvalue=True, offvalue=False,command = self.callback)
chb_view_on_moon.grid(column= 0, row= 4,pady = 10)
self.canvas = tk.Canvas(fr_canvas, bg='white', width = self.canv_w, height=self.canv_h)
self.canvas.grid(column = 0, row = 0)
def callback(self,*args):
if self.lbl_view.get()==True:
self.view_on_moon = ViewOnMoon(parent = self.master)
else:
self.vom.destroy()
if __name__=="__main__":
root = tk.Tk()
app = GuiMoonMove(master = root)
app.mainloop()
I am writing a GUI with the screen of Raspberry.Each time I destroy a GUI and call a new GUI there will be a delay of about a few seconds to make the user see the raspberry's desktop. I want to draw a loading interface down to the background so that when I switch the screen the user won't see the raspberry desktop. I use this code:
from tkinter import *
class Load_Screen:
def __init__(self, master):
self.master = master
self.master.configure(background='white')
self.frame = Frame(self.master)
self.frame.pack()
self.canvas = Canvas(self.frame, width = 350, height = 250)
self.canvas.configure(background='white')
self.canvas.pack()
self.img = PhotoImage(file="image/loading.png")
self.canvas.create_image(55,150, anchor=W, image=self.img)
newWindow = Toplevel(self.master)
newWindow.geometry("700x500")
app = Main_Screen(newWindow)
class Main_Screen:
def __init__(self, master):
self.master = master
self.frame = Frame(self.master)
self.frame.pack()
def main():
root = Tk()
root.geometry("760x600")
app = Load_Screen(root)
root.mainloop()
if __name__ == '__main__':
main()
However, the loading screen overrides the main screen. And I want the opposite, the bottom loading screen and the main screen above
This is my solution which i have found at
How to make a Tkinter window jump to the front?
from tkinter import *
class Load_Screen:
def __init__(self, master):
self.master = master
self.master.configure(background='white')
self.frame = Frame(self.master)
self.frame.pack()
self.canvas = Canvas(self.frame, width = 350, height = 250)
self.canvas.configure(background='white')
self.canvas.pack()
self.img = PhotoImage(file="image/loading.png")
self.canvas.create_image(55,150, anchor=W, image=self.img)
newWindow = Toplevel(self.master)
newWindow.geometry("700x500")
app = Main_Screen(newWindow)
class Main_Screen:
def __init__(self, master):
self.master = master
self.frame = Frame(self.master)
self.frame.pack()
def main():
root = Tk()
root.geometry("760x600")
root.lift()
app = Load_Screen(root)
root.mainloop()
if __name__ == '__main__':
main()
Use root.lift() make Load_Screen below Main_Screen
I cannot figure out how to use the tag_bind method associated with a canvas. I created an oval and expected to be able to generate an event by clicking on it. When I do this, nothing happens. What is the correct use of tag_bind?
import tkinter as tk
class Window():
def __init__(self, master):
self.master = master
self.create_widgets()
def create_widgets(self):
self.c = tk.Canvas(self.master, bg='white', height=200, width=300)
self.c.pack()
b = tk.Button(self.master, text='Draw', command=self.draw)
b.pack()
def draw(self):
self.c.delete('all')
self.oval = self.c.create_oval([30,50], [130,80])
self.rect = self.c.create_rectangle([180,10], [280,80])
self.c.tag_bind(self.oval, '<Button-1>', self.oval_func)
def oval_func(self, event):
self.c.delete(self.rect)
self.c.create_text(150, 150, text='Hello, world!', anchor='w')
if __name__ == '__main__':
root = tk.Tk()
app = Window(root)
root.mainloop()
The code is working. However, when you bind to a canvas object, you have to click on part of the drawn object. Since you didn't fill the oval, that means you must click on its outline.
If you fill it with the same color as the background (or any other color) you can click anywhere in the oval.
self.oval = self.c.create_oval([30,50], [130,80], fill="white")
This question already has answers here:
Python Tkinter Canvas fail to bind keyboard
(3 answers)
Closed 5 years ago.
I am trying to make a Python Tkinter program display a circle and move the circle right when I press Return/Enter. My code is currently:
from Tkinter import *
class GUI(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.setupStuff()
def setupStuff(self):
self.canvas = Canvas(self, height=500, width=600)
self.canvas.pack()
self.blueCircle = self.canvas.create_oval(10, 10, 40, 40, fill='dodger blue')
self.canvas.bind('<Return>', self.moveRight)
def moveRight(self):
print 'Yo',
self.canvas.move(self.blueCircle, 1, 0)
print 'yo'
if __name__ == '__main__':
window = GUI(Tk())
window.mainloop()
My problem is that the ball doesn't move when I press Return/Enter.
You may bind your keys to root which is self.master in your case instead of binding it to canvas. Please see the modified working code below.As #Alex has specified, bind returns an event
from Tkinter import *
class GUI(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.setupStuff()
def setupStuff(self):
self.canvas = Canvas(self, height=500, width=600)
self.canvas.pack()
self.blueCircle = self.canvas.create_oval(10, 10, 40, 40, fill='dodger blue')
#self.canvas.bind('<Return>',self.moveRight)
self.master.bind('<Return>', self.moveRight)
def moveRight(self, event = None):
print 'Yo',
self.canvas.move(self.blueCircle, 200, 0)
print 'yo'
if __name__ == '__main__':
root = Tk()
window = GUI(root)
window.mainloop()
You need to focus the tkinter canvas with the .focus_force() method if you want the widget to receive events, as only the focused widget can receive events. Also, when the your keypress handler is called, it passes an argument containing data about the event, so you need to add an argument to moveRight or you will get a TypeError.
from Tkinter import *
class GUI(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.setupStuff()
self.canvas.focus_force() #force the canvas to take focus
def setupStuff(self):
self.canvas = Canvas(self, height=500, width=600)
self.canvas.pack()
self.blueCircle = self.canvas.create_oval(10, 10, 40, 40, fill='dodger blue')
self.canvas.bind('<Return>', self.moveRight)
def moveRight(self, eventData): #.bind passes an argument
self.canvas.move(self.blueCircle, 1, 0)
if __name__ == '__main__':
window = GUI(Tk())
window.mainloop()
I am new to python so I was trying to make a GUI, in that I have to place a button in a particular position.
I tried using self.nxt_form.place(x=200,y=100) instead of self.nxt_form.pack().
But the button disappeared and only the frame appeared when it ran. Can you tell me how to place the button in a particular position?
Here is the code:
import tkinter as tk
class Main_form:
def __init__(self, root,title="Simulated MTBF"):
self.root = root
self.frame = tk.Frame(self.root)
"""Button nxt_form which moves to next form"""
self.nxt_form = tk.Button(self.frame, text = 'Next Form', width = 25,command = self.new_window)
self.nxt_form.pack()
self.frame.pack()
"""command to open new window by clicking Button """
def new_window(self):
self.newWindow = tk.Toplevel(self.root)
self.app = Demo2(self.newWindow)
class Demo2:
def __init__(self, root):
self.root = root
self.frame = tk.Frame(self.root)
self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
self.quitButton.pack()
self.frame.pack()
def close_windows(self):
self.root.destroy()
def main():
root = tk.Tk()
app = Main_form(root)
root.mainloop()
if __name__ == '__main__':
main()
when i am using tkinter i used column and row to position objects
self.btn = tk.Button(self, text = "button")
self.btn.grid(row = 1, column = 1)
EDIT - expanded on information in response to comment (below)
I would make an label and change its width and height to make the spacing you need (note im a beginer at python as well so this is probly a bad way but it works)
from tkinter import *
import tkinter as tk
from tkinter.ttk import Combobox,Treeview,Scrollbar
class MainMenu(Frame):
def __init__(self, master):
""" Initialize the frame. """
super(MainMenu, self).__init__(master)
self.grid()
self.create_GUI()
def create_GUI(self):
frame1 = tk.LabelFrame(self, text="frame1", width=300, height=130, bd=5)
frame1.grid(row=0, column=0, columnspan=3, padx=8)
#the frame is not needed but it is a good thing to use as can group
#parts of your interface together
self.text1 = Entry(frame1)
#note if you were not using frames would just put self here
self.text1.grid(row = 1, column = 0)
self.text2 = Label(frame1, text = "",height = 10)
self.text2.grid(row = 2 , column = 0)
self.text3 = Entry(frame1)
self.text3.grid(row = 3, column = 0)
root = Tk()
root.title("hi")
root.geometry("500x500")
root.configure(bg="white")
app = MainMenu(root)
root.mainloop()
Also note that you can not use pack and grid together what you could do is group your objects in different frames then use grid in one frame and pack in a different frame. I personally prefer to use grid to pack as it gives you more control over your object then pack does