I have a little python program. I'm using Tkinter for a GUI. I have a bunch of grid style text boxes, but i want to add a small text area. All the examples Ive tried work, but open in a new window.
I want the last grid labeled "description" to be a small text area instead, As it would be used for a few sentences rather than a few words. Also im going to need to "get()" this input to use as a variable.
Here is my script.( I left out a few parts that might bring up errors )
from Tkinter import *
master = Tk()
Label(master, text="Stock #").grid(row=0, sticky=W)
Label(master, text="Type").grid(sticky=W, row=1)
Label(master, text="Make").grid(sticky=W, row=2)
Label(master, text="Model").grid(sticky=W, row=3)
Label(master, text="GVW").grid(sticky=W, row=0, column=2)
Label(master, text="Description").grid(sticky=W, row=1, column=2)
e1 = Entry(master)
e2 = Entry(master)
e3 = Entry(master)
e4 = Entry(master)
e24 = Entry(master)
e25 = Entry(master)
e1.grid(row=0, column=1, pady=5, padx=(0,30))
e2.grid(row=1, column=1, pady=5, padx=(0,30))
e3.grid(row=2, column=1, pady=5, padx=(0,30))
e4.grid(row=3, column=1, pady=5, padx=(0,30))
e24.grid(row=0, column=3, pady=5, padx=(0,10))
e24.insert(0, "N/A")
e25.grid(row=1, column=3, pady=5, padx=(0,10))
e25.insert(0, "N/A")
mainloop( )
I want the last grid labeled "description" to be a small text area instead, As it would be used for a few sentences rather than a few words.
As the Entry docs tell you:
To enter multiple lines of text, use the Text widget.
So:
text = Text(master)
text.grid(row=whatever, etc.)
Also im going to need to "get()" this input to use as a variable.
I'm not sure what you mean here. If you mean you wanted to attach a StringVar, you can't do that with Text, sadly, only with Entry. But if you want to be able to fetch the contents in some way, you don't care which way, then that's easy; the Text docs will show you how a variety of different ways, but I think text.get(1.0, END) is the one you'll probably want.
Related
I tried to follow the lesson on databases in this youtube video from freecodecamp. However, when I wrote my code and executed it, an entry box and a label are stuck on top of my button to submit a record. I don't know how to fix this issue.
Using rowconfigure didn't help either and the label is still stuck on top of the submit button.
Also, for every label and button that I add, even if the button's row is smaller than the label's row, the label is displayed before the button in the GUI.
label and entry box on top of button
I have removed all the database elements from my code as they are not relevant to the problem I am facing. Here is my code:
from tkinter import *
window = Tk()
window.geometry("400x400")
# Create function to Delete a record
def delete():
pass
# create submit function
def submit():
pass
# create query function
def query():
pass
f_name = Entry(window, width=30)
f_name.grid(row=0, column=1, pady=(10, 0))
l_name = Entry(window, width=30)
l_name.grid(row=1, column=1)
address = Entry(window, width=30)
address.grid(row=2, column=1)
city = Entry(window, width=30)
city.grid(row=3, column=1)
province = Entry(window, width=30)
province.grid(row=4, column=1)
p_code = Entry(window, width=30)
p_code.grid(row=5, column=1)
# Create text box label
f_name_label = Label(window, text="First Name")
f_name_label.grid(row=0, column=0, pady=(10, 0))
l_name_label = Label(window, text="Last Name")
l_name_label.grid(row=1, column=0)
address_label = Label(window, text="Street")
address_label.grid(row=2, column=0)
city_label = Label(window, text="City")
city_label.grid(row=3, column=0)
province_label = Label(window, text="Province")
province_label.grid(row=4, column=0)
p_code_label = Label(window, text="Postal Code")
p_code_label.grid(row=5, column=0)
# Create submit button
submit_btn = Button(window, text="Add record to database", command=submit)
submit_btn.grid(rows=6, column=0, columnspan=2, pady=10, padx=10, ipadx=100)
# create a query button
query_btn = Button(window, text="Show Records", command=query)
query_btn.grid(rows=7, column=0, columnspan=2, pady=10, padx=10, ipadx=125)
delete_box = Label(window, text="ID Number")
delete_box.grid(row=8, column=0)
delete_box = Entry(window, width=30)
delete_box.grid(row=8, column=1)
# create a delete button
delete_btn = Button(window, text="Delete Record", command=delete)
delete_btn.grid(rows=9, column=0, columnspan=2, pady=10, padx=10, ipadx=125)
window.mainloop()
What mistake have I made?
Edit: Thanks for the responses. It turns out that it was just a typo (rows instead of row) that caused the problem. But now I am curious to know how did my previous code give that particular output? Shouldn't it have thrown an error saying that rows is an invalid keyword argument? Moreover, when the row parameter was not even given for submit_btn, how was it correctly placed below "Postal Code"? Why exactly was there an overlap of the label, entry and button?
The reason for your output is really interesting and involves some minute details in tkinter.
Key Observations:
After experimenting with your code, I made the following observations:
rows is equivalent to rowspan and columns is equivalent to columnspan
When row is not given in the .grid statement, it is taken to be <index-of-last-occupied-row> + 1. On the other hand, the default value of column is fixed at 0.
Explanation for the Undesired Output:
Let's first figure out which is the last occupied row after p_code_label is added.
p_code_label = Label(window, text="Postal Code")
p_code_label.grid(row=5, column=0)
p_code_label is present in row[5] and it is the last occupied row.
Next, the buttons are displayed using grid as explained below:
# Create submit button
submit_btn = Button(window, text="Add record to database", command=submit)
submit_btn.grid(rows=6, column=0, columnspan=2, pady=10, padx=10, ipadx=100)
In the above grid statement, row has not been given. Therefore, submit_btn is added to row[5+1=6] and spans 6 rows (due to rows=6).
Now, the last occupied row = 6 + (6-1) = 11.
# create a query button
query_btn = Button(window, text="Show Records", command=query)
query_btn.grid(rows=7, column=0, columnspan=2, pady=10, padx=10, ipadx=125)
As row is once again not given above, query_btn is added to row[11+1=12] and spans 7 rows.
Now, the last occupied row = 12 + (7-1) = 18.
Note that even though submit_btn and query_btn span multiple rows, they appear to be spanning only 1 row because none of the rows have been assigned any weights.
delete_box = Label(window, text="ID Number")
delete_box.grid(row=8, column=0)
delete_box = Entry(window, width=30)
delete_box.grid(row=8, column=1)
Unlike the previous two widgets, the above two widgets have been given a row. Thus, they occupy row[8] and are displayed on top of the submit_btn. The button is almost completely covered vertically even though the above two widgets are present in only one of the rows spanned by submit_btn. This is because the rows do not have any weights.
If all the rows spanned by submit_btn are assigned weights and the button is gridded using sticky=NSEW, the output would be as given below:
(The vertical centre of 6 rows would be in between two rows. That's the reason why Add record to database is displayed between row[8] and row[9].)
By now, the reason for the overlap of the label, entry and button should be clear.
For the sake of completion, I will also explain how is delete_btn added.
# create a delete button
delete_btn = Button(window, text="Delete Record", command=delete)
delete_btn.grid(rows=9, column=0, columnspan=2, pady=10, padx=10, ipadx=125)
The above widget is added to row[18+1=19] and spans 9 rows.
Thus, the last occupied row = 19 + (9 - 1) = 27.
I did not make any minor changes except to rearrange in order(Label, Entry and Button) for row index (6,7,8,9).
Also, it's bad for putting Entry widget any where before mainloop().
Always start after row=5. Then you can put Entry widget there.
I rearrange code to make readability widgets order..
Code:
delete_box = Label(window, text="ID Number")
delete_box.grid(row=6, column=0)
delete_box = Entry(window, width=30)
delete_box.grid(row=6, column=1)
# Create submit button
submit_btn = Button(window, text="Add record to database", command=submit)
submit_btn.grid(row=7, column=0, columnspan=2, pady=10, padx=10, ipadx=100)
# create a query button
query_btn = Button(window, text="Show Records", command=query)
query_btn.grid(row=8, column=0, columnspan=2, pady=10, padx=10, ipadx=125)
# create a delete button
delete_btn = Button(window, text="Delete Record", command=delete)
delete_btn.grid(row=9, column=0, columnspan=2, pady=10, padx=10, ipadx=125)
window.mainloop()
Screenshot:
I am trying to make my own gui with Python. I am using Tkinter and eventhough I made the buttons show text, the text won´t show up.
import classes
root = Tk()
root.geometry('395x400')
e = Entry(root, width=60, borderwidth=5)
e.grid(row=0, column=0, columnspan=3, padx=10, pady=10)
#buttons
button_add_student=Button(root, name="add student", padx=90, pady=20, command=)
button_show_student=Button(root, name="enter", padx=90, pady=20, )
button_add_student.grid(row=1, column=0)
button_show_student.grid(row=1, column=1)
root.mainloop() ```
They don't show text but you haven't given them any text to show. If you want a button to have a textual label then you need to provide a value to the text attribute:
button_add_student=Button(root, text="add student", ...)
button_show_student=Button(root, text="enter", ...)
You were using the name attribute, which specifies the internal name for the widget. The name is only visible if you print out the string representation of the widget (eg: print(str(button_add_student))).
In Tkinter in Python:
I have a table with a different label. How can I justify the text that is in the label? Because It is a table and the texts in different labels come together!
from tkinter import *
root=Tk()
a=Label(root,text='Hello World!')
a.pack()
a.place(x=200,y=200)
b=Label(root,text='Bye World')
b.pack()
b.place(x=200,y=100)
I want something for justifying in center some text in label but it is not something that I need plz check this: link
By default, the text in a label is centered in the label. You can control this with the anchor attribute, and possibly with the justify attribute. justify only affects the text when there is more than one line of text in the widget.
For example, to get the text inside a label to be right-aligned you can use anchor="e":
a=Label(root,text='Hello World!', anchor="e")
Note, however, this will appear to have no effect if the label is exactly big enough to hold the text. In your specific example, you would need to give each label the same width:
a=Label(..., width=12)
b=Label(..., width=12)
To add on to what Bryan said, LEFT is the constant you are looking for to correctly format your wrapped text. You can also justify to the RIGHT or CENTER (the default).
a=Label(root,text='Hello World!', anchor="e", justify=LEFT)
instead of using .pack() i would use .grid()
The Tkinter Grid Geometry Manager
grid will allow better management of your components
find bellow an example of usage and management:
Label(root, text="First").grid(row=0, sticky=W)
Label(root, text="Second").grid(row=1, sticky=W)
entry1 = Entry(root)
entry2 = Entry(root)
entry1.grid(row=0, column=1)
entry2.grid(row=1, column=1)
checkbutton.grid(columnspan=2, sticky=W)
image.grid(row=0, column=2, columnspan=2, rowspan=2,
sticky=W+E+N+S, padx=5, pady=5)
button1.grid(row=2, column=2)
button2.grid(row=2, column=3)
you would endup using the grid option padx="x" to "justify" your labels
I am creating a GUI wherein I have a TextBox, and a few Buttons.
The problem is, the layout seems to be scrambled. And when I increase the row number so that I could space out well, it doesn't make any difference. I am not sure where I have made a mistake.
Code:
from Tkinter import *
from tkFileDialog import *
gui = Tk() #create an object
gui.title("xyz")
gui.geometry("900x300")
GuiLabel1 = Label(gui,text="hi everyone!!!!!!")
GuiLabel1.grid(row=0, column=0)
GuiLabel2 = Label(gui,text="File")
GuiLabel2.grid(row=1, column=0)
bar=Entry(gui)
bar.grid(row=1, column=1)
button1= Button(gui, text="Browse")
button1.grid(row=1, column=2)
button2= Button(gui, text="Process")
button2.grid(row=2, column=2)
button3= Button(gui, text="ABC")
button3.grid(row=3, column=0)
button4= Button(gui, text="ABC")
button4.grid(row=3, column=1)
button5= Button(gui, text="ABC")
button5.grid(row=3, column=2)
button6= Button(gui, text="ABC")
button6.grid(row=3, column=3)
button7= Button(gui, text="ABC")
button7.grid(row=3, column=4)
gui.mainloop()
See the below image for the screenshot of the GUI:
The widgets are appearing pretty much exactly as you have told them to appear. The problem is, you are relying on a lot of defaults for positioning which is probably why they don't appear on the screen the way you think they should.
When you use grid, you should almost always include the sticky option to define how a widget will fill the cell it has been placed in. You often need to augment that with padding. Finally, you should generally give at least one row and one column a non-zero weight.
Also, remember that you're creating a grid. If you have a very wide item in the grid, that will cause the entire column to be wide. If you place smaller items in subsequent rows they will by default be centered in that column.
You can use the "width=" parameter to evenly space widgets see http://effbot.org/tkinterbook/button.htm and row/columnconfigure to show empty rows/columns
from Tkinter import *
gui = Tk() #create an object
gui.title("xyz")
gui.geometry("900x300")
GuiLabel1 = Label(gui,text="hi everyone!!!!!!")
GuiLabel1.grid(row=0, column=0)
GuiLabel2 = Label(gui,text="File")
GuiLabel2.grid(row=3, column=0)
bar=Entry(gui)
bar.grid(row=1, column=1)
button1= Button(gui, text="Browse", width=test_width)
button1.grid(row=1, column=2)
button2= Button(gui, text="Process", width=test_width)
button2.grid(row=2, column=2)
test_width=20
for ctr in range(4):
button= Button(gui, text="ABC"+str(ctr+1), width=test_width)
button.grid(row=3, column=ctr)
## empty column between
gui.columnconfigure(4, minsize=50)
button7= Button(gui, text="ABC")
button7.grid(row=3, column=5)
gui.mainloop()
I Think you may be looking for a mixture of
pack()
grid()
and also the element Frame which allows you to 'group' elements in it that count as one element.
I can not fix your code but I suggest you look into those and have a try.
This is my code so far:
master = Tk()
Label(master, text="Input:").grid(row=0)
e1 = Entry(master, width = 100)
e1.grid(row=0, column=1)
Button(master, text='Q', command=q_pressed).grid(row=3, column=2,
sticky=W, padx = 4, pady=4)
Button(master, text='C', command =c_input).grid(row=3, column=1,
sticky=W, padx = 0, pady=4)
Button(master, text='Confirm', command=parse_input).grid(row=3, column=0,
sticky=W, padx = 4, pady=4)
I am trying to make it so that "Q" button is next to the "C" button (like how "C" is next to the "Confirm" button) but it instead places it where the Entry widget ends.
I understand this is a grid management issue. How do I set up a layout so row = 0, has text and entry widget and row=3 has its own independent columns (0,1,2) for the buttons?
Your problem is that the Entry e1 is very long and contains 100 characters, but it spans only one column. You can use columnspan to define the number of used columns for e1 in the grid command. Following example with columnspan = 30 works for me. Decide yourself, what would be a reasonable value for columnspan.
from Tkinter import *
master = Tk()
Label(master, text="Input:").grid(row=0)
e1 = Entry(master, width = 100)
e1.grid(row=0, column=1, columnspan=30)
Button(master, text='Q').grid(row=3, column=2)
Button(master, text='C').grid(row=3, column=1)
Button(master, text='Confirm').grid(row=3, column=0)
mainloop()
There is possibly more than one way to perform the layout you want, I choose to present a clean one. Your Entry widget occupies a large horizontal space in the second column of the first row, thus placing widgets below it in the next row is going to cause you trouble. Since you know you will have 3 buttons below it, you could make this Entry span two columns (columnspan=2 while gridding it) and play with that while gridding the next row. But I prefer a different approach, which also produces a better layout overall. What you want is to grid a Frame in the second row that takes two columns (since in the row above it you have two widgets). Then you grid your buttons on this new Frame.
This turns your code into:
import Tkinter
master = Tkinter.Tk()
Tkinter.Label(master, text="Input:").grid(row=0, column=0)
Tkinter.Entry(master, width = 100).grid(row=0, column=1)
frame = Tkinter.Frame()
frame.grid(row=1, column=0, columnspan=2, sticky='w')
Tkinter.Button(frame, text='Confirm').grid(row=0, column=0, sticky='w')
Tkinter.Button(frame, text='C').grid(row=0, column=1, sticky='w')
Tkinter.Button(frame, text='Q').grid(row=0, column=2, sticky='w')
master.mainloop()
enter code here{ master = Tk()
Label(master, text="Input:" ).grid(row=0)
e1 = Entry(master, width=100)
e1.grid(row=0, column=1, columnspan=10)
Button(master, text='Q', width=5, command=q_pressed).grid(row=3, column=1, padx=0, ipadx=5, pady=4, sticky=E)
Button(master, text='C', width=5, command =c_input).grid(row=3, column=1, padx=0, ipadx=5, pady=4, sticky=W)
Button(master, text='Confirm', width=10, command=parse_input).grid(row=3, column=0, padx=0, pady=4, sticky=W)
mainloop()}
Since you wanted 100 char for entry string I based my cell/column width on 10 for simple math division. Set my columnspan to 10. I got rid of padx since it pertains to border width and used ipadx which pertains to inner text width. Made entry set to 10 columns wide of 10 char. Used "input" text as 1 column. This will allow me to use 10 char or one column for text "confirm" and I can break column 1 in half by making button "c" & "q" 5 char wide using width=5. Then by using justfy put "c" West and "q" East.
There are many ways this is just easiest in my mind.