Position the button in right place Tkinter - python

How can I position the two button close to eachother. I am getting the output as shown in the picture below.
_scrape_btn = ttk.Button(_mainframe, text='Scrape!', command=save)
_scrape_btn.grid(row=2, column=0)
_compress_btn = ttk.Button(_mainframe, text='Compress!', command=compress)
_compress_btn.grid(row=2, column=1)

Looking at your image, I can tell that your URL and Content LabelFrames have been put into row=0, column=0 and row=1, column=0 respectively. So you should now realise that the width of the first column is as large as the labelframe. Hence your 2nd button starts where the 1st column ends since it on the 2nd column.
What you can do is add columnspan=2 in both the labelFrames.
Now by default the buttons will be center aligned. To bring them close together, you need to add sticky='e' in the grid command of the 1st button (Scrape) and sticky='w' in the grid command of the 2nd button (Compress).

Related

Setting tkinter Text yview / Text view area

I would like to set the tkinter Text box's view area / yview to a specific area. How do I do this? I know that one can retrieve the current yview but have been unsuccessful in setting it to a desired value. I know that it can be set to the desired value because I am getting the yview, destroying the Text box, and then recreating the text box. From there I would like to set the view area to what it was before but am having trouble. What should I do?
Example yviews:
(0.0, 1.0)
(0.07407407407407407, 1.0)
Code:
#Define the Text widget
t = Text(window)
t.pack()
for i in range(100):
t.insert(END, "{}\n".format(i))
def get_y():
global y
y = t.yview()
b = Button(window, text="get y", command=get_y)
b.pack()
b1 = Button(window, text="set y", command=lambda: t.yview(MOVETO, y[0]/y[1]))
b1.pack()
The code above gets the user very close but it always goes a little up or down and isn't quite right. What should I do to fix it? Can this be done similarly with xview?
I figured it out. We can get the yview with t.yview() but we can't just insert a yview value and expect it to use it. Instead, we must use t.yview(MOVETO, yview[0]). This gives it a value it can work with and goes to about the correct position
NOTE:
The same can be done with xview but use xview[1] instead

List of tkinter widget using a loop doesn't show up

Please allow me to explain the problem I am facing. I am a undergraduate student who started learning Python a couple of month ago. So, I am new and please bear with me if the experts found them rather naive.
The intention was very simple. I want to place 5 menu buttons in parallel (say in one row, well, this is not the pressing issue though) in a tkinter parent frame. What I did was to introduce 5 sub-frames and place the menu button on them one by one. The idea to use sub-frame was to make space for centering and better layout. Using the most straight-forward fashion, I did it one by one: Define a sub-frame and place a menu button. It all worked well.
Now I am trying to avoid the repeated codes and to lay out the menu buttons and sub-frames using for loops, since the sub-frames and buttons are technically identical except the gird locations and labels are different. I came up with the following code.
Python compiler didn't report any errors. But, only the last button ("Other") was displayed while other buttons are missing. I am having difficulty sorting out what exactly went wrong.
indBtnFrame = [tkinter.Frame(self.parent)] * 5
for i in range(len(indBtnFrame)):
column_index = (i+1)*2
indBtnFrame[i].grid(column=column_index,
row=0,
columnspan=2,
rowspan=1,
sticky="WENS")
for r in range(1): # 1 row in total.
indBtnFrame[i].rowconfigure(r, weight=1)
for c in range(1): # 1 column in total.
indBtnFrame[i].columnconfigure(c, weight=1)
# To fix the grid size.
indBtnFrame[i].grid_propagate(False)
indBtnLabel = ["Street",
"City",
"Postcode",
"Province",
"Other"]
indBtn = []
for i in range(len(indBtnLabel)):
button_label = tkinter.StringVar()
button_label.set(str(indBtnLabel[i]))
temp_widget = tkinter.Menubutton(indBtnFrame[i],
textvariable=button_label,
relief=tkinter.GROOVE)
indBtn.append(temp_widget)
for i in range(len(indBtn)):
indBtn[i].grid(column=0, row=0,
columnspan=1, rowspan=1,
sticky="WENS")
indBtn[i].menu = tkinter.Menu(indBtn[i], tearoff=0)
indBtn[i]["menu"] = indBtn[i].menu

Trouble with .grid() in python 3 with buttons

So i'm trying to position 2 buttons on my tkinter GUI, but it seems that setting the row and column aren't working as they should. If i set the grid row/column to a value the button will move over a bit, then if i try to set the button grid again, it won't move anymore. Wondering if the way i created the button is affecting the grid function? All in all im just trying to position my buttons, and I can't seem to get them to move.
#Play button creation
btnPlay = Button(app, text ="Play", command = playMusic)
btnPlay.grid(row =10, column = 10)
#Pause button creation
btnPause = Button(app)
btnPause.grid()
btnPause.configure(text = "Stop", command = stopMusic)
Rows and columns have a size of zero if they don't contain anything. Putting something in column 10, when there is nothing in columns 0-9 is the same as putting it in column 0.

Multiple frames in a single tab ttk.Notebook

I have the following sections of code (not complete) where I would like to contain several frames into a single tab in the ttk 'Notebook' .
win1 = Tk()
n = ttk.Notebook(win1)
choice_frame = ttk.Frame(n, style="Black.TLabel")
choice_frame.grid(row=2, column=1, sticky="N,S,E,W", padx=1, pady=1)
choice_frame.grid_columnconfigure(0, weight=3)
choice_frame.grid_rowconfigure(0, weight=1)
frame_text = ttk.Frame(n, style="Black.TLabel")
frame_text.grid(row=0, column=0, sticky = "N")
frame_text.grid_columnconfigure(0, weight=3)
frame_text.grid_rowconfigure(0, weight=1)
frame_table = ttk.Frame(n, style="Black.TLabel")
frame_table.grid(row=2, column=0, padx=1, pady=1, sticky= " N, S, E, W ")
frame_table.grid_columnconfigure(0, weight=3)
frame_table.grid_rowconfigure(0, weight=1)
n.add(frame_table, text="One") # Would like same tab not two separate ones
n.add(choice_frame, text="One")
n.grid(sticky="N")
I would also like to know if there's a way of allowing every dimension to adjust automatically when the window is dragged out and maximised. I have previously tried:
frame_table.grid_propagate(0)
But this doesn't seem to allow the height as well as width dimension to stick. I would like my 'table' to be in the center of the window but adjust with the window size.
Thank you for your help!
grid_propagate isn't a solution to any of your problems.
Each tab can contain only a single frame, but that single frame can contain whatever you want. So, create one container frame for the tab and then put all your other frames in the container frame. This is one of the main reasons the Frame class exists -- to build widget containers that facilitate layout.
As for the resizing, the problem is probably that you're not adding a weight to the rows and columns of the main window. Though it could also be related to the fact you are using grid to place the frames in the notebook; you can't use grid to place items in a notebook.

Finding widgets on a grid (tkinter)

Using the tkinter module, suppose I create a grid with 50 button widgets and each of those widgets has different text. I need to be able to specify some way of typing in a row and column so I can get that widget's text at that location.
For example, if I need the widget's text at the third row in the second column of the grid. I've searched the docs but that tells me how to get info about widgets, when I need info about the grid.
There's no need to create your own function or keep a list/dictionary, tkinter already has a built-in grid_slaves() method.
It can be used as frame.grid_slaves(row=some_row, column=some_column)
Here's an example with a grid of buttons showing how grid_slaves() retrieves the widget, as well as displaying the text.
import tkinter as tk
root = tk.Tk()
# Show grid_slaves() in action
def printOnClick(r, c):
widget = root.grid_slaves(row=r, column=c)[0]
print(widget, widget['text'])
# Make some array of buttons
for r in range(5):
for c in range(5):
btn = tk.Button(root, text='{} {}'.format(r, c),
command=lambda r=r, c=c: printOnClick(r, c))
btn.grid(row=r, column=c)
tk.mainloop()
You got a previous answer relative to a method to save button objects in a dictionary in order to recover them using their (column, row) position in a grid.
So if self.mybuttons is your dictionary of lists of buttons as described in previous answer, then you can get the text at position row, col as this:
abutton = self.mybuttons[arow][acolumn]
text_at_row_col = abutton["text"]
On the other hand, if what you need is to get the text from the button callback:
button.bind("<Button-1>", self.callback)
then you can get the button text from the event, you do not need to know its row/col position, only to press it:
def callback(self, event):
mybutton = event.widget
text_at_row_col = mybutton["text"]

Categories

Resources