I am trying to make a date chooser using python. I am using spinboxes, however I was wondering whether I could get all 5 widgets into one grid space, so it seemed like all 5 widgets are really one widget. Hopefully the following code articulates the problem better.
import tkinter as tk
root=tk.Tk()
Day=tk.IntVar()
Month=tk.IntVar()
Year=tk.IntVar()
Label1=tk.Label(root,text="Label Label Label Expanding Row")
Label1.grid(row=1,column=1)
DayEntry=tk.Spinbox(root,textvariable=Day,bg="white",from_=0, to_=31,width=2)
DayEntry.grid(row=2,column=1)
MonthEntry=tk.Spinbox(root,textvariable=Month,bg="white",from_=0, to_=12,width=2)
MonthEntry.grid(row=2,column=3)
YearEntry=tk.Spinbox(root,textvariable=Year,bg="white",from_=2000, to_=20019,width=4)
YearEntry.grid(row=2,column=5)
Divider1=tk.Label(root,text="/")
Divider1.grid(row=2,column=2)
Divider2=tk.Label(root,text="/")
Divider2.grid(row=2,column=4)
root.mainloop()
The solution is to put all of the widgets in a frame.
datepicker = tk.Frame(root)
datepicker.grid(row=2, column=0)
DayEntry=tk.Spinbox(datepicker,textvariable=Day,bg="white",from_=0, to_=31,width=2)
MonthEntry=tk.Spinbox(datepicker,textvariable=Month,bg="white",from_=0, to_=12,width=2)
YearEntry=tk.Spinbox(datepicker,textvariable=Year,bg="white",from_=2000, to_=20019,width=4)
Divider1=tk.Label(datepicker,text="/")
Divider2=tk.Label(datepicker,text="/")
DayEntry.grid(row=0,column=1)
Divider1.grid(row=0,column=2)
MonthEntry.grid(row=0,column=3)
Divider2.grid(row=0,column=4)
YearEntry.grid(row=0,column=5)
Related
I code in Python and I use tkinter quite a lot to create GUIs for my applications. I prefer to make my GUIs look round and modern rather than sharp cornered boxes. For buttons and labels I tend to use PhotoImage to use self-made images that provide a cleaner look.
My GUIs look really modern now but the only issue is that I have Entry widgets for users to enter data. They still look really boxy and rectangular, which makes them stand out from the rest of the modern look. My question is, that is there a method in tkinter like PhotoImage, that makes the Entry Widget look better?
This is the current way I make entry widgets:
from tkinter import *
root = Tk()
e = Entry(root)
e.pack()
root.mainloop()
When I say make entries look nicer I mean:
Smoother Corners
Rounded Edges
Just a less boxy look
I hope someone can help me.
Thanks
U can place ur sharp corner image & place your tkinter entry on it , sure to add entry bg color same as images color.
import tkinter as tk
root = tk.Tk()
#read image for entry
entry_bg_image=PhotoImage(
file=r"file.extension")
#add frame for entry
entry_frame = tk.Frame(root)
entry_frame.pack()
#place your rounded corner image.
#for entry bg
entry_bg =tk.Label(entry_frame,
image=entry_bg_image)
entry_bg.place(rely=0 ,relx=0)
#place entry
entry = tk.Entry(entry_frame
,bg=same_as_image)
entry.place(relx=0,rely=0)
root.mainloop()
On python tkinter, I am using 2 different frames on a Toplevel window, one on the right and another on the left.
The frame which is on right side is not scrollable. I have created a canvas on top of the frame on that frame and one more frame on top of that canvas. I have made that canvas scrollable and pasted the widgets on that canvas but it's not scrollable. I am attaching the code of the scrollable part.
w1 = Canvas(frame2, width=600, height=300,background="white", scrollregion=(1500,1500,3000,3000))
scr_h1 = ttk.Scrollbar(frame2,orient=HORIZONTAL)
scr_h1.pack(side=BOTTOM,fill=X)
scr_h1.config(command=w1.xview)
scr_v1 = ttk.Scrollbar(frame2,orient=VERTICAL)
scr_v1.pack(side=RIGHT,fill=Y)
scr_v1.config(command=w1.yview)
w1.config(xscrollcommand=scr_h1.set,yscrollcommand=scr_v1.set)
w1.pack(fill=BOTH,expand=True)
This code works for me running Python 3.4 - a tkinter window pops up with a red oval (for testing), and the scrollbar allows you to navigate the frame. If you are using Python 2, change tkinter to Tkinter (capital T).
from tkinter import *
root = Tk()
frame2 = Frame(root)
frame2.pack(side=RIGHT)
w1 = Canvas(frame2, width=600, height=300,background="white", scrollregion=(0,0,3000,3000))
scr_h1 = Scrollbar(frame2,orient=HORIZONTAL)
scr_h1.pack(side=BOTTOM,fill=X)
scr_h1.config(command=w1.xview)
scr_v1 = Scrollbar(frame2,orient=VERTICAL)
scr_v1.pack(side=RIGHT,fill=Y)
scr_v1.config(command=w1.yview)
w1.config(xscrollcommand=scr_h1.set,yscrollcommand=scr_v1.set)
w1.pack(fill=BOTH,expand=True)
# inserted to see if it's actually scrolling
w1.create_oval(0,0,50,50,fill='red')
root.mainloop()
Two Possible Issues
Why were you using a ttk ScrollBar? The simple tkinter scroll bar will suffice for your code. When things aren't working, it might help to go back to the simpler model.
Why your starting scroll region was 1500 - any object placed on the canvas in the first 1500 units in either direction were not visible, with this setting, which may have given you the illusion that the scrollbar was not working. See http://effbot.org/zone/tkinter-scrollbar-patterns.htm for more information on using scroll bars.
It should not matter that there are two frames or their orientation, though you may run into problems if you try to mix managers (grid,pack,etc.). These problems are more along the lines of stalled programs, not stationary scrollbars.
I am running into a problem with a tkinter program, I have the LabelFrame grouping a set of labels and entries, however, it is not grouping my widgets. My code for the LabelFrame is as follows:
(edit: i managed to get the Label to display, however, it is not grouping my widgets.)
root=Tk()
message_frame=LabelFrame(root,text="testing",padx=0,pady=0,width=100,height=100).grid(padx=5,pady=10)
message_label=Label(message_frame,text="Message").grid(row=1,column=0,sticky=W)
pub_label=Label(message_frame,text="Public Key").grid(row=2,column=0,sticky=W)
priv_label=Label(message_frame,text="Public Key").grid(row=3,column=0,sticky=W)
message_entry=Entry(message_frame,textvariable=message,width=50).grid(row=1,column=1,sticky=W)
pub_entry=Entry(message_frame,textvariable=pub_key,width=50).grid(row=2,column=1,sticky=W)
priv_entry=Entry(message_frame,textvariable=private_key,width=50).grid(row=3,column=1,sticky=W)
In Tkinter, the typical workflow is to create a widget and then place it using some geometry manager on two separate lines.
If I'm not mistaken, the .grid method on Tkinter widgets returns None. So if you print message_frame right after you create it, you will probably see that it is None. When you use that passed to the next widgets, they assume you want to put it on the root widget...
The easy fix is to do something like:
message_frame=LabelFrame(root,text="testing",padx=0,pady=0,width=100,height=100)
message_frame.grid(row=0,column=0)
And you probably want to do the same with all the widgets since I doubt you actually want pub_label = priv_label = None ...
Give the frame some size attributes:
from Tkinter import *
root = Tk()
message_frame = LabelFrame(root,text="testing",padx=0,pady=0,width=100,height=100).grid(row=0,column=0,padx=5,pady=10)
Once the width and height are defined, the frame shows up fine.
If you post some of your frame's contents, it might make it clearer if this is not the issue.
I am experimenting with Tkinter, as I was trying to figure out is there a way to set the tkinter's window size without using canvas. I came upon this how to set frame size question on SO's Question & Answer. So I went ahead and test it by writing a very small program to display a text label. But I found out it is "missing", or disappear when I use frame.pack_propagate(0)
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, width=400, height=400)
# Does not work at the moment, textBox is missing
# frame.pack_propagate(0)
frame.pack()
textBox = tk.Label(frame, text="(x,y): ")
textBox.pack()
root.mainloop()
So my question is, can you explain why my textBox (Label) is not appearing when I use the frame.pack_propagate(0) instead of frame.pack() method? And secondly, is there a way to set the window size without using a canvas? I want to know because I am writing a series of small programs to teach my friend about tkinter, before introducing canvas to him. It would be nice if the window size are all the same across my tkinter samples. And I am just wondering as well (curious). Thank you very much.
I am using python 3.2.2 on MAC OS 10.5.8.
pack_propagate only sets a flag, it doesn't cause the frame to be placed in the widget. It is not a substitute for calling pack.
In other words you must do this:
# put the frame in its parent
frame.pack()
# tell frame not to let its children control its size
frame.pack_propagate(0)
# put the textbox in the frame
textBox.pack()
To answer your second question: Yeah, there is a way.
tkinters Tk do have the Tk.geometry function. When you just call it without arguments, you will get the current geometry in form of 'widthxheight+x+y', so for example (on Windows 10) '200x200+26+26' when you create your first Tk window. Using that format you can resize the Tk by, e.g., writing: root.geometry('400x500+60+60') to set the width to 400, the height to 500 and place it at the coordinates (60|60).
This works for Tk alswell as for Toplevel. But Toplevel also takes the arguments height and width when initialized or configured. If you want them to keep their size when packing something inside just use root.pack_propagate(False) on them.
By the way there is something similar for the grid manager: root.grid_propagate(False)
How do I randomly add buttons to a Tkinter GUI? I need it to be able to create a button, then put it anywhere on the window, is this possible? I am using Python 2.6 on Windows.
If you want random button placement (or anything not aligned along a grid, etc.), you can use the place geometry manager. Depending on platform, overlapped buttons may not behave as you expect, though, so you may want to avoid them.
Here's a simple example:
from Tkinter import *
from random import random
root = Tk()
frame = Frame(root, height=200, width=200)
for i in range(10):
Button(frame, text=str(i)).place(x=random() * 150, y=random() * 180)
frame.pack()
root.mainloop()
There are several options to choose from. For example, you could design on a grid where you have six buttons per row. Then it's just a matter of starting at row 0, incrementing the column for each button. When you get to the last column, reset the column to 0 and increment the row by one.
Another option is to use a text widget as the container, and embed your buttons in the text widget with wrapping enabled. With this trick the buttons will fill a row automatically and wrap if the user grows or shrinks the main windows. It's a tiny bit more work, but it works well if that's the behavior you want.