PyQt4 Dynamically created radiobuttons and default checking - python

I want to dynamically create radiobuttons for every year from 2013. I've already created these buttons but I am not able to check the first radiobutton(2013). To do that I am using QtGui.QRadioButton('2013').setChecked(True)
I have no idea what I am missing...
def dynamicaly_cratede_radiobtns(self):
current_year = datetime.today().year
self.button_group = QtGui.QButtonGroup()
for i in range(2013, current_year+1):
self.button_name = QtGui.QRadioButton("{}".format(i))
self.button_name.setObjectName("radiobtn_{}".format(i))
self.verticalLayout.addWidget(self.button_name)
self.button_group.addButton(self.button_name,i)
self.button_name.toggled.connect(self.subplot_year)
QtGui.QRadioButton('2013').setChecked(True)
def subplot_year(self):
print self.button_group.checkedId()
EDIT
I just solved it by using if
for i in range(2013, current_year+1):
self.button_name = QtGui.QRadioButton("{}".format(i))
self.button_name.setObjectName("radiobtn_{}".format(i))
self.verticalLayout.addWidget(self.button_name)
self.button_group.addButton(self.button_name,i)
self.button_name.toggled.connect(self.subplot_year)
if i == 2013:
self.button_name.setChecked(True)
But anyway, why does the original approach doesn't work? I think it is more elegant solution.

QtGui.QRadioButton('2013').setChecked(True)
creates a new radio button with text value of '2013'. This one gets checked.
This radio button is not part of any layout or radio group and thus non of the buttons is checked.
It seems like you think the radio buttons get cached somewhere and can be accessed with the text value. But this is not the case.
To solve this issue you need to check one of the buttons you added to the layout like you did in your edit.

Related

Implementing checkable buttons in Pyqt5 file menu to act similarly to radio buttons

I have created a file menu in PyQt5 with a "File" option with two checkable buttons (button1, button2). Unfortunately, I have not found a way to implement radio buttons into the file menu so I assume at the moment it is not possible. Instead, I would like to make these two checkable buttons act like radio buttons - this means that if one is checked the other becomes unchecked. Only one can be checked at a given time.
I have attempted to do it this way (which I find the most logical and straightforward), but it does not work:
def fileMenu(self):
if self.button1.isChecked() == True:
self.button2.setChecked(False)
If I check button2 and then check button1, button2 does not uncheck. Is there any other way to do this or any error in my code preventing it from working? Or... ideally is there any way to implement radio buttons into the file menu?
You can accomplish this using a QActionGroup. You would have to group all those buttons together under an action group. It will not work otherwise.
The documentation can be found here.
Here is an example of implementing a QActionGroup with two radio buttons:
w is your QtMainWindow, ag is defining the QActionGroup, and menu is the name of your menu.
ag = QtGui.QActionGroup(w, exclusive=True)
a = ag.addAction(action_a)
menu.addAction(a)
b = ag.addAction(action_b)
menu.addAction(b)

Radiobutton IN tkinter

I m creating a GUI for a simple quiz and I want my answer to be checked in radiobutton . But the problem is that I can not mark or unmark it , its always set up marked . my code is
R1=Radiobutton(win,text= 'option1',command =sel1)
My function sel1 is as follow :
def sel1():
global ans
ans = 1
As far as I see from the docs the radiobutton is used to select one out of many, whcih as I understand will always require one button to be marked. It's possible you need CheckButton.
EDIT: As it turned out the problem was to set common variable for all radio buttons as mentioned in the docs linked above.

Is it ok to create and place a tkinter widget at the same time?

I am new in Python and in tkinter so the question may seems naive: is it ok to create and place widgets at the same time if I don't need to change them?
It works but is it a good practice? And if not why?
An example of what I mean:
import tkinter as tk
window=tk.Tk()
tk.Label(window,text='Lost Label').pack()
window.mainloop()
To expand upon #Skynet's answer....
Whenever you do Widget(*args, **kwargs).pack() the pack() method returns None as would other geometry managers, so if you tried to assign this to a variable the variable would be None.
In this case then probably not, since you probably actually want to be storing the reference to the widget.
If you don't need a reference then there's not really a problem with it. As the other answer notes you don't need a definitve reference to every single widget in your GUI unless you plan to use this reference in some way. Unless I plan on changing the label text / modifying it in someway then I typically use your method to save some space. No need to write more code than you have to!
For example you're creating a Button widget.
btn = Button(blabla, text="Button1")
This returns a button object and if you need later to configure it or get information about it you can do it by through the btn variable.
But if you use something like btn = Button(blabla, text="Button1").pack() it returns None and not a button object so you won't be able to change anything about the button or get information about it later.
Another example is with the Entry widget
entry = Entry(blabla)
Using that later you can do entry.get() to get the text inside the entry
but you won't be able to do it if you use entry = Entry(blabla).pack() since it doesn't return an entry object, it just packs the widget and you won't be able to access it for later use.
There is nothing wrong with that approach and I have already seen it quite a few times. You don't have to keep a reference to every widget in your GUI.

Big number of pushbuttons and smart checking which is checked

I have dialog:
It contains many flat QPushButtons, QTextEdit and another QPushButton. After click on 'Get list' we can see list of checked buttons in QTextEdit.
My question is how to get this functionality in some smart way. Right now I'm checking every button:
if self.ui.bq6o.isChecked():
cards.append("Q6o")
if self.ui.bk2o.isChecked():
cards.append("K2o")
if self.ui.bq3o.isChecked():
cards.append("Q3o")
if self.ui.bt7s.isChecked():
cards.append("T7s")
if self.ui.bq4o.isChecked():
cards.append("Q4o")
if self.ui.bt4s.isChecked():
cards.append("T4s")
if self.ui.b98o.isChecked():
cards.append("98o")
if self.ui.bjto.isChecked():
cards.append("JTo")
if self.ui.btt.isChecked():
cards.append("TT")
if self.ui.bq7o.isChecked():
cards.append("Q7o")
[...]
Obviously I can't like code like that. I was looking for some widget "button matrix" like, but without luck. I will be grateful for advises.
All the buttons should be children of the same widget, probably the dialog itself. Just get a handle to that widget to get all the child buttons, then loop through them and if they're checked, included their text.
parent = dialog # or whatever
cards = [widget.text() for widget in parent.children() if isinstance(widget, QPushButton) and widget.isChecked()]
You may need to include some code in the if statement to exclude the "Get List" button, or any other pushbuttons in your dialog that could be set to "checked" but shouldn't be included in cards list.
As #Brendan suggested in the other question, you could loop through them in a single list comprehension. But one other approach is to connect each buttons toggled signal to a slot that allows them to register when they are checked.
# somewhere in your class
self.checkedList = set()
def buttonChecked(self, checked):
button = self.sender()
if checked:
self.checkedList.add(button)
else:
if button in self.checkedList:
self.checkedList.remove(button)
# when you create a new button
button.toggled.connect(self.buttonChecked)
This would let you always have a set of just the checked buttons, which are self reporting. Otherwise, you would have to track them under their parent and loop to find out which are checked each time.
Update
Here is a another version that combines #Brendans loop and my signal suggestion. This might help in a situation where your buttons are a bit more spread out across your UI as opposed to be all under a single parent... but first assuming them all under a parent...
parent = dialog
for widget in parent.children():
if isinstance(widget, QPushButton):
widget.toggled.connect(self.buttonChecked)
You could repeat this in your __init__() for all the locations of your buttons and get them all registered to the slot.

PyQt - Radiobuttons not checkable

I want to display the result of an SQL query with radio buttons. For this purpose, I use an array of radiobuttons. This works fine, it displays what I want. The problem I have is that the buttons are not "checkable". If I click on them, nothing happens. I'm sure it is a stupid mistake, but I can't see what's wrong.
Here is my code :
groups = select.getGroups(self.parent.db) #This returns a list of strings
self.groupList = {}
self.groupBtn = []
i = 0
radioLayout = QtGui.QVBoxLayout()
radioGroup = QtGui.QGroupBox()
for g in groups:
self.groupList[g[0]] = i
name = g[0]
self.groupBtn.append(QtGui.QRadioButton(name))
radioLayout.addWidget(self.groupBtn[i])
i = i+1
radioGroup.setLayout(radioLayout)
self.groupBtn[0].setChecked(True)
self.groupLayout.addWidget(radioGroup)
Is there something obvious I'm missing ?
"Radio buttons typically present the user with a "one of many" choice. In a group of radio buttons only one radio button at a time can be checked; if the user selects another button, the previously selected button is switched off."
If that is not your desired behaviour, you may consider using check buttons (QCheckButton). If it is:
You need to be sure that you have not incidentally set setAutoExclusive(false) somewhere in code, for any of those radio buttons (by default it is set on true).
Last thing I can suggest (based on the code that you have shown): Try to put radio buttons in QButtonGroup() instead of QGroupBox().

Categories