I want to set title for TopLevel, but TopLevel shows title of Root. I think that my next script corresponds with examples from TkInter documentation, but gives me bad result. Cann You explain me, why my setting master.title = 'Top' in class AppTop does not set new title for TopLevel?
import tkinter as tk
class AppTop(tk.Frame):
def __init__(self, master):
mon_h = 900
mon_w = 1250
master.title = 'Top'
tk.Frame.__init__(self, master)
master.minsize(height = 900, width = 600)
fr_button = tk.Frame(master)
fr_button.place(relx=0.01, rely=0.06)
butArrowPlus = tk.Button(fr_button, text=">", height = 1, width = 20, command=self.Cmd)
butArrowPlus.grid(column= 1, row= 1)
return
def Cmd(self):
return
class Application(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
frRoot = tk.Frame(master, width=700, height=400, bd=2)
frRoot.place(relx=0.1, rely=0.1, anchor="nw")
butIllumBall = tk.Button(frRoot, text= 'Light Ball', height = 1, width = 20, command=self.cmd_illuminated_ball)
butIllumBall.grid(column= 0, row= 0, pady=10)
master.minsize(height = 250, width = 300)
master.title('Root')
def cmd_illuminated_ball(self):
top = tk.Toplevel()
top.transient(self.master)
top.grab_set()
app = AppTop(master = top)
app.mainloop()
return
wndRoot = tk.Tk()
appapp = Application(master=wndRoot)
appapp.mainloop()
You try to set Toplevel title with:
master.title = 'Top'
but the correct syntax is:
master.title('Top')
There are a couple of additional things: You do not need an additional mainloop for the Toplevel window. From the code it looks like you think that the Toplevel is a new application, instantiating it with app = AppTop(master = top). But it's just a new window which runs under the appapp.mainloop().
AppTop() inherits from tk.Frame() but you never use it. Instead you put all the widgets directly in the Toplevel (master) window. Same goes for Application() as well.
Related
I am using the following code, I am having 2 issues,
1. When I try to maximize the window, the Entry widget is not aligned/maximized along with main window and see a gap between scrolled text and Entry widget.
2. Second I am trying to set my cursor in Entry widget when I try to open or whenever my app is active but it's not working for some reason. Any Idea what am I making mistakes?
import tkinter as tk
from tkinter import scrolledtext
class Main:
def __init__(self, master):
self.master = master
master.title("Main")
width = master.winfo_screenwidth()
height = master.winfo_screenheight()
master.minsize(width=1066, height=766)
master.maxsize(width=width, height=height)
self.frame = tk.Frame(self.master)
text_area = scrolledtext.ScrolledText(self.master,width=75,height=35)
text_area.pack(side="top",fill='both',expand=True)
text_entry = tk.Entry(self.master,width=65)
text_entry.pack(side="top",fill=X, expand=True,ipady=3, ipadx=3)
text_entry.configure(foreground="blue",font=('Arial', 10, 'bold', 'italic'))
text_entry.focus()
self.frame.pack()
def initial(self):
print ("initializing")
def main():
root = tk.Tk()
app = Main(root)
root.mainloop()
if __name__ == '__main__':
main()
I can address the issue of your entry field not expanding properly.
That is because you have fill=X and this is not a valid input for fill. Instead use fill="x". I believe your 2nd issue with the entry field having a large gap is because you have set expand = True instead change that to expand = False.
That said I prefer to use the grid() geometry manager instead. Take a look at my below example of how to do this with grid and weights.
When using the grid() manager you can tell each widget exactly where you want it along a grid. The use of weights is for telling a row or column how much if any it should expand with the window. This combined with sticky="nsew" will help us control stuff expands within the window.
import tkinter as tk
from tkinter import scrolledtext
class Main(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("Main")
width = self.winfo_screenwidth()
height = self.winfo_screenheight()
self.minsize(width=1066, height=766)
self.maxsize(width=width, height=height)
self.rowconfigure(0, weight=1)
self.rowconfigure(1, weight=0)
self.columnconfigure(0, weight=1)
text_area = scrolledtext.ScrolledText(self,width=75,height=35)
text_area.grid(row=0, column=0, ipady=3, ipadx=3, sticky="nsew")
text_entry = tk.Entry(self,width=65)
text_entry.grid(row=1, column=0, ipady=3, ipadx=3, sticky="ew")
text_entry.configure(foreground="blue",font=('Arial', 10, 'bold', 'italic'))
text_entry.focus()
def initial(self):
print ("initializing")
if __name__ == '__main__':
root = Main()
root.mainloop()
Update:
To clarify on your issue with fill and expand I have updated your code with the correction so you can see it working.
import tkinter as tk
from tkinter import scrolledtext
class Main:
def __init__(self, master):
self.master = master
master.title("Main")
width = master.winfo_screenwidth()
height = master.winfo_screenheight()
master.minsize(width=1066, height=766)
master.maxsize(width=width, height=height)
self.frame = tk.Frame(self.master)
text_area = scrolledtext.ScrolledText(self.master,width=75,height=35)
text_area.pack(side="top",fill='both',expand=True)
text_entry = tk.Entry(self.master,width=65)
text_entry.pack(side="top",fill="x", expand=False, ipady=3, ipadx=3)
text_entry.configure(foreground="blue",font=('Arial', 10, 'bold', 'italic'))
text_entry.focus()
self.frame.pack()
def initial(self):
print ("initializing")
def main():
root = tk.Tk()
app = Main(root)
root.mainloop()
if __name__ == '__main__':
main()
looking through blogs, tutorials and such, I have not been able to understand why the following code will not display a Label in a Frame. I can perform this task well when I do not define a class, but I want to create this application to be able to create Frames and other widgets more dynamically. Here is the code. init works fine and displays a Frame in the root window appropriately. the code runs with out any errors. I have added print statements and print(type()) statements through out the add_heading function, but still no label gets displayed. Hopefully someone can tell me what I am doing wrong. Thanks in advance
#!/usr/bin/python3
from tkinter import *
class CompFrame(Tk):
def __init__(self, parent, rows, columns, title):
Frame.__init__(self, parent)
self.root = parent
f_w = screen_width/3
f_h = screen_height * .90
self = LabelFrame(root, text=title, width=f_w, height=f_h, bg="light grey")
self.grid_columnconfigure(columns, weight=1)
self.grid(row=rows, column=columns)
self.grid_propagate(False)
def add_heading(self, title):
label_width=12
ftitle = Label(self, text=title)
ftitle.configure(font='Helvetica 24 bold', width=label_width)
ftitle.place(x=".5i", y=".2i")
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
root.geometry("%dx%d%d%d" % (screen_width,screen_height,0,0))
Calibrator = PhotoImage(file="image1.png")
Feeeder = PhotoImage(file="image2.PNG")
frame1 = CompFrame(root, 0, 0, "Component 1")
frame1.add_heading("NATURAL")
root.mainloop()
The self = LabelFrame(root ... part is guilty, maybe try something like this to keep control on the labelframe :
from tkinter import *
class CompFrame(Frame): # Edit with Bryan Oakley comment
def __init__(self, parent, rows, columns, title):
Frame.__init__(self, parent)
self.root = parent
f_w = screen_width/3
f_h = screen_height * .90
self.labelframe = LabelFrame(root, text=title, width=f_w, height=f_h, bg="light grey")
self.labelframe.grid_columnconfigure(columns, weight=1)
self.labelframe.grid(row=rows, column=columns)
self.labelframe.grid_propagate(False)
def add_heading(self, title):
label_width=12
ftitle = Label(self.labelframe, text=title)
ftitle.configure(font='Helvetica 24 bold', width=label_width)
ftitle.place(x=5, y=2)
I am trying to make an entry widget display beneath a Label using the .grid() function; however, it is simply not showing up. Here is my code:
#demonstrates how to use a class with Tkinter
from Tkinter import *
import tkMessageBox
class Application(Frame):
def __init__(self, master):
""" Initializes the Frame"""
Frame.__init__(self, master)
self.grid()
self.create_widgets()
def create_widgets(self):
self.previous_trans = Text(width = 100, height = 5, wrap = WORD)
self.previous_trans.grid(row = 0, column = 0, columnspan = 2)
self.items = Text(width = 50, height = 16, wrap = WORD)
self.items.grid(row = 1, column = 1, rowspan = 14, sticky = E)
self.additem = Label(text = "Add Item")
self.additem.grid(row = 1)
self.myentry = Entry(self)
self.myentry.grid(row = 2)
root = Tk();
root.title("Work In Progress")
app = Application(root)
root.mainloop();
The reason is because:
you don't specify a row or column for app, so it defaults to 0,0
you don't specify a parent for self.previous_trans so it defaults to the root window -- the same as for the application frame
you explicitly put self.previous_trans in row zero, column zero, which overwrites the label
You need to be giving an explicit parent of self to all of the widgets inside of Application:
self.previous_trans = Text(self, ...)
self.items = Text(self, ...)
self.additem = Label(self, ...)
self.myentry = Entry(self, ...)
Tkinter experts, I'm having trouble getting a Canvas to scroll. This is my second GUI, and I've done something similar before, so I don't know what I'm doing wrong. I'd appreciate any help you can offer.
Here's a minimal version of what I'm trying to do. I'm using python 3.4.3 on Windows 10.
import tkinter as tk
import tkinter.font as tk_font
import tkinter.ttk as ttk
import random
def get_string_var(parent, value=''):
var = tk.StringVar(parent)
var.set(value)
return var
class SummaryFrame(ttk.Frame):
def __init__(self, parent, **kwargs):
ttk.Frame.__init__(self, parent, **kwargs)
var_names = ['label_'+str(num) for num in range(1, 20)]
self.vars = {}
for name in var_names:
self.vars[name] = get_string_var(self)
self._add_summary_labels(self, self.vars, 1)
#staticmethod
def _add_summary_labels(frame, vars, start_row):
current_row = start_row
for name in vars:
tk.Label(frame, text=name, anchor=tk.N+tk.W).grid(row=current_row, column=0, sticky=tk.N+tk.S+tk.W+tk.E)
text_label = tk.Label(frame, wraplength=200, textvariable=vars[name], anchor=tk.N+tk.W, justify=tk.LEFT)
text_label.grid(row=current_row, column=1, sticky=tk.W)
current_row += 1
def set_summary_fields(self, info):
for name in info:
if name in self.vars:
self.vars[name].set(info[name])
class OuterFrame(ttk.Frame):
def __init__(self, parent, **kwargs):
ttk.Frame.__init__(self, parent, **kwargs)
self.canvas = tk.Canvas(self)
scrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL, command=self.canvas.yview)
self.canvas.configure(yscrollcommand=scrollbar.set)
self.summary = SummaryFrame(self.canvas)
self.summary.pack(fill=tk.BOTH, expand=1)
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
scrollbar.pack(side=tk.LEFT, fill=tk.Y, expand=1)
label_text = {}
for i in range(1, 20):
label_text['label_'+str(i)] = "information " * random.randint(1, 20)
self.set_fields(label_text)
def set_fields(self, info):
self.summary.set_summary_fields(info)
self.canvas.configure(scrollregion=(1, 1, self.summary.winfo_width(), self.summary.winfo_height()))
if __name__ == "__main__":
root = tk.Tk()
frame = OuterFrame(root)
frame.pack(fill=tk.BOTH, expand=1)
root.mainloop()
The scrollbar should change when the contents of the inner SummaryFrame expands, but doesn't. It remains grayed out and inoperable. What am I doing wrong?
Short answer: you are configuring the scrollregion to be one pixel by one pixel.
You are configuring the scrollregion based on the width and height of the self.summary, but you are doing this before the window has a chance to be mapped to the screen. The width and height, therefore, are both one.
You need to wait for the window to be drawn before computing the width and height of the window.
I created a Frame and then a Canvas.
What I want to do next is to add a Button on the Canvas.
However, when I packed the Button I cannot see the Canvas!
Here is what I tried:
from Tkinter import Tk, Canvas, Frame, Button
from Tkinter import BOTH, W, NW, SUNKEN, TOP, X, FLAT, LEFT
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Layout Test")
self.config(bg = '#F0F0F0')
self.pack(fill = BOTH, expand = 1)
#create canvas
canvas1 = Canvas(self, relief = FLAT, background = "#D2D2D2",
width = 180, height = 500)
canvas1.pack(side = TOP, anchor = NW, padx = 10, pady = 10)
#add quit button
button1 = Button(canvas1, text = "Quit", command = self.quit,
anchor = W)
button1.configure(width = 10, activebackground = "#33B5E5",
relief = FLAT)
button1.pack(side = TOP)
def main():
root = Tk()
root.geometry('800x600+10+50')
app = Example(root)
app.mainloop()
if __name__ == '__main__':
main()
The Tkinter pack manager tries to resize the parent widget to the correct size to contain its child widgets, and no larger, by default. So the canvas is there - but it's precisely the same size as the button, and thus invisible.
If you want to place a widget on a canvas without causing the canvas to dynamically resize, you want the Canvas.create_window() function:
# ... snip ...
button1 = Button(self, text = "Quit", command = self.quit, anchor = W)
button1.configure(width = 10, activebackground = "#33B5E5", relief = FLAT)
button1_window = canvas1.create_window(10, 10, anchor=NW, window=button1)
This will create your button with upper-left corner at (10, 10) relative to the canvas, without resizing the canvas itself.
Note that you could replace the window argument with a reference to any other Tkinter widget. One caveat, though: the named widget must be a child of the top-level window that contains the canvas, or a child of some widget located in the same top-level window.
you can use button1.place(x=0,y=0) geometry manager instead of pack(side =TOP)
pack resize the master widget to makes it large enough to hold the child widget
http://effbot.org/tkinterbook/pack.htm#Tkinter.Pack.pack_propagate-method
http://effbot.org/tkinterbook/place.htm
I had the exact same problem. There isn't an official way that I know, but here's a way around it:
from Tkinter import *
root = Tk()
def clicked(event):
print("pressed")
canvas1 = Canvas(root, relief = FLAT, background = "#D2D2D2")
canvas1.pack()
buttonBG = canvas1.create_rectangle(0, 0, 100, 30, fill="grey40", outline="grey60")
buttonTXT = canvas1.create_text(50, 15, text="click")
canvas1.tag_bind(buttonBG, "<Button-1>", clicked) ## when the square is clicked runs function "clicked".
canvas1.tag_bind(buttonTXT, "<Button-1>", clicked) ## same, but for the text.
root.mainloop()