PyQt - Radiobuttons not checkable - python

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

Related

how to create a pop up menu which is linked with listbox in tkinter?

I'm trying to create a listbox in which pressing 'Enter key' AKA <Return> will
pop up a menu in front of the row selected, like this
I tried using this example but it seems that menu pops up only where the mouse is located
Is what I'm asking even possible to do? If so, how can I get the x,y locations of any row in the listbox?
sadly, I couldn't even provide a pseudo code to explain further because I have no idea what it would even look like, so please pardon my lack of clarity
The curselection method of the listbox will return a list of selected items. The bbox method of the listbox will give the coordinates of an item relative to the listbox itself. You can use winfo_rootx and winfo_rooty to get the absolute coordinates of the listbox on the screen. You can use all of this information to place the menu near the selected item.
For example:
def show_popup(event):
selection = event.widget.curselection()
if selection:
item = selection[0]
rootx = event.widget.winfo_rootx()
rooty = event.widget.winfo_rooty()
itemx, itemy, itemwidth, itemheight = event.widget.bbox(item)
popup_menu.tk_popup(rootx+event.widget.winfo_width()-10, rooty+itemy+10)

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)

Enabling a checkbox Tkinter (Python 3.4)

I have a CheckBox in Tkinter. I want it to always stay checked but disabling the checkbox destroys the looks of the GUI application. I want to keep its state as Normal and if a user tries to uncheck it the box remains checked, or rechecks itself immediately after.
global ghistory
ghistory = IntVar()
cc = Checkbutton(frame3, text="History", variable=ghistory)
cc.select()
cc.pack()
How do I do it?
Add a function that sets the variable to True. A quick lambda function would do the trick:
cc=tk.Checkbutton(frame3,text="History",variable=ghistory, command=lambda:ghistory.set(1))
Or you could use the select command:
cc=tk.Checkbutton(frame3,text="History",variable=ghistory)
cc['command'] = cc.select
use .cget('state') to see if the button is disabled...
self.widget_checkbutton = tk.Checkbutton(self, variable=self.some_variable, command=lambda:self.stay_checked())
def stay_checked(self):
if self.widget_checkbutton.cget('state') == 'disabled':
self.widget_checkbutton.select()
else:
self.widget_checkbutton.deselect()
#this will only let the button be checked if widget is active.
(so basically, if some widget is disabled... you tell the checkbox to stay the same. else if some widget is normal, you allow the checkbox to work normally... select... deselect...)

PyQt4 Dynamically created radiobuttons and default checking

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.

How do I read what's been selected in a MULTIPLE listbox

I'm very new to Python and can't get my head round how to capture just ONE item that's been selected from a listbox, let alone more than one. I particularly don't understand WHEN the items I select are noted by the program because there is no "command" option with a listbox. I think that is so. I don't really understand binding. I think that's my problem (amongst others!).
The following code is extracted from my "app" class.
l = Listbox(self, height=10, selectmode=EXTENDED)
# Selectmode can be SINGLE, BROWSE, MULTIPLE or EXTENDED. Default BROWSE
l.grid(column=0, row=11, sticky=(N,W,E,S))
s = Scrollbar(self, orient=VERTICAL, command=l.yview)
s.grid(column=0, row=11, sticky=(N,S,E))
l['yscrollcommand'] = s.set
for i in range(1,101):
l.insert('end', 'Line %d of 100' % i)
self.ichoose = l.curselection()
As you experts will realise, when I print app.ichoose, I just get an empty tuple.
What do I need to do?
Thanks,
John Rowland
Normally the item is selected when a user clicks on it, and the default binding fires. If you want to print it out (or do anything else) as soon as possible once that happens, create a binding on the event <<ListboxSelect>>. This event will be generated immediately after the selection has changed, even if it changed via the keyboard.
okay... the way I've done this in the past is by:
listbox.bind("<Double-Button-1>", entered)
which then the function entered would look something like this:
def entered(event):
global listEx
items = map(int, listbox.curselection())
result= listEx[items[0]]
print result
listEx is a list of all the entries in the listbox, and the items = map(int, listbox.curselection()) section will return the index value of the selected entry... if you want to get multiple values, I imagine it would be very simple to for loop through the values in items
EDIT:
def entered(event):
print listbox.selection_get()
will just print out the selection from the listbox, the reason I like to use my double mouse click is because it is much more likely to be a real world use, normally I use double click and <Return> as standard listbox controls, especially if in a use with multiple selections as yours

Categories