Trouble with .grid() in python 3 with buttons - python

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.

Related

Changing the background colour of loop generated entry boxes based on user input in tkinter

I have the following code where I use a for loop to create some entry boxes.
# loop to create labels and entry boxes for main table
for i in range(int(self.number_of_indicators)): # columns
for j in range(int(self.project_length_entry.get())): # rows
# creating labels, using list of indicator names
indicator_target_label = Label(frame, text=str(self.indicator_names[i].get()))
# create entry box
self.indicator_month_entry = Entry(frame)
# adding labels to screen
indicator_target_label.grid(row=100, column=3+i)
# add entry box to screen
self.indicator_month_entry.grid(row=101 + j, column=3+i)
# end for loop
# end for loop
I want to be able to change the background colour of the boxes to one of three colours based on the user input (in the boxes where there is user input) after clicking the 'confirm button' - this input will be an integer number.
I have created the button with the following code:
# create button
sf_button = Button(frame, text='Confirm', command=lambda: sf_button)
# add button to screen
sf_button.grid(row=200, column=2)
I have tried using the following code for the button function (the numbers at the moment are arbitrary :
def sf_button():
if float(self.indicator_month_entry.get()) == 2:
self.indicator_month_entry.configure(bg='yellow')
elif float(self.indicator_month_entry.get()) > 3:
self.indicator_month_entry.configure(bg='blue')
else:
self.indicator_month_entry.config(bg='red')
This runs fine, but doesn't do what I want.
Do I need to assign the entry boxes to a list and address them that way? How will that account for n number of boxes?

Pyside2 build several buttons and memory

I have built a application which contained multi QComboBox.
On change, each one add buttons (about 100) in a grid layout, here a part of the called function:
for x in xrange(1,100):
my_list_shots.append(str(x))
x=2 # line 1 has the menu
y=1 # row
incrementLineX=1 # every 10 we go to line 2 (x+1) and reset incrementLine and y (row) to 1
for i in xrange(1,121):
try:
my_shot_number=my_list_shots[i]
my_shot_number = "%03d"%int(my_shot_number)
self.buttons = QtWidgets.QPushButton(my_shot_number,self)
self.buttons.setStyleSheet("background-color:brown;color:white")
self.buttons.clicked.connect(partial(self.my_open_mov,my_shot_number))
self.my_grid_layout.addWidget(self.buttons,x,y,1,1)
except Exception as e:
self.buttons = QtWidgets.QPushButton("",self)
self.buttons.setEnabled(False)
my_shot_number=""
y=y+1
incrementLineX=incrementLineX+1
if incrementLineX>10:
x=x+1
y=1
incrementLineX = 1
self.buttons.clicked.connect(partial(self.my_open_mov,my_shot_number))
and so on...
I worried about the memory, if I keep my window open all day long with many changes, I'll create each time 99 buttons? or not..?
How can I properly build my buttons?
Do I need to destroy them when I call the function?
In another way, what I want is to replace new buttons by old ones and I don't want to create thousand of buttons if I keep the windows open.
I just need the way to do it.
I have got the solution.
I use deleteLater() for each created buttons before to rebuild new ones.
# DELETE THE OLD WIDGET IN THE LAYOUT GRID
def clearShotsWidget(self):
while self.shotsWidgetLayout.count():
item = self.shotsWidgetLayout.takeAt(0)
item.widget().deleteLater()
self.shotsWidgetLayout.removeItem(item)
The other idea is to put all the build buttons in a list and delete them before to create the new ones.
Thanks a lot
Gui

Position the button in right place Tkinter

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).

Python 'grid()' ignores row/column/sticky options

I'm trying to make a lil' card game. It's one player, against a CPU, and it's just as simple as that. A game. However, games aren't fun if they aren't played by the rules, and in this case, the .grid() doesn't want to play by it's rules (.grid(row, column, sticky). The code executes fine, console reports no error, and it compiles, executes, and "works" completely. However, the image label doesn't move at all.
NOTE: I'm not sure if it's because of the method that I use to display images, if it doesn't work with images, or it's just plain bugged.
Here's the code, as well as the output.
Python
crdImg = []
usrStk = None
cpuStk = None
i = 1
#define cards
while i < 57:
i = i + 1
crdImg.append('img/cards/%s.png' % (i - 1))
usrStk = crdImg[54]
cpuStk = crdImg[55]
#define card images
usrCrdImg = Image.open(usrStk)
usrCrdBg = ImageTk.PhotoImage(usrCrdImg)
usrCrd = tkinter.Label(self, text="", image=usrCrdBg, borderwidth=1)
usrCrd.grid(row=4, column=4)
usrCrd.image = usrCrdBg
usrCrd.pack()
Output
It seems you are first positioning the label with grid, but then overriding that position with pack. Do not use grid and pack layout managers together!
Remove the line usrCrd.pack() and change CardGame(root).pack() to CardGame(root).grid(), then it should work.
Note, however, that unless you put something into the other rows and columns, usrCrd.grid(row=4, column=4) will still put the card in the top-left corner, as the other rows and columns have zero width and height.

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