I have A LOT of QComboBoxes, and at a certain point, I need to fetch every item of a particular QComboBox to iterate through.
Although I could just have a list of items that correspond to the items in the QComboBox, I'd rather get them straight from the widget itself (there are a huge amount of QComboBoxes with many items each).
Is there any functions / methods that will do this for me?
(Eg:
QComboBoxName.allItems()
)
I've looked through the class reference but couldn't find anything relevant.
I've thought of a few messy methods, but I don't like them.
(Like iterating through the QComboBox by changing the index and getting the item, etc).
Python 2.7.1
IDLE 1.8
Windows 7
PyQt4
As far as I can tell, you can just reference an item using .itemText():
AllItems = [QComboBoxName.itemText(i) for i in range(QComboBoxName.count())]
Building on the accepted answer, you can actually give you combobox a method callable using combo_box.allItems(), by doing this:
setattr(combo_box, "allItems", lambda: [combo_box.itemText(i) for i in range(self.ui.combo_box.count())])
print(combo_box.allItems()) # Works just fine!
I believe it has to be done in the scope where combo_box was born, otherwise setattr fails.
Tested in PyQt5 and Python 3.7.
Related
In maya, I want to make an OpenMaya MSelectionList (api version 2.0) with more than one item in it... I've only been able to fill it with the add method like so:
import maya.api.OpenMaya as om
selList = om.MSelectionList()
selList.add('node1')
selList.add('node2')
selList.add('node3')
That's ok for populating it with just a few items, but it's tedious if you have more... I'm wondering if there's a way to do something more like this:
import maya.api.OpenMaya as om
selList = om.MSelectionList(['node1', 'node2', 'node3'])
I could write my own function to create an empty MSelectionList, loop through a list, and add them and then return it; I'm just wondering I have completely looked over something obvious? From what I can tell on the docs, you can only create an empty MSelectionList, or create one by passing in another MSelectionList (to basically duplicate it).
If this can't really be done inherently in the class, does anyone have an idea why it was implemented this way?
The MSelectionList is ultimately a wrapper around a C++ list of object pointers (the Maya api is unusual in that uses diffeent function sets to work on different aspects of an object, rather than the more familiar use of a classic inheritance tree).
Implementing variadic functions in C++ is not trivial (especially not back in the 90s when the Maya API was designed. I suspect nobody felt it was worth the time for what's essentially syntactic sugar.
sl = om.MSelectionList()
for node in nodelist:
sl.add(n0de)
or
sl = om.MSelectionList()
[sl.add(n0de) for node in nodelist]
although I would not recommend the shorter version, which produces an list of meaningless Nones as a side effect
I am trying to set up a signal-slot arrangement in PyQt where the signal transmits a lot of information. I want to use a QObject as a carrier by setting the various information I want to transmit as attributes of the QObject. In theory, this should work - there is a QSignalMapper.setMapping() overload which takes a sender and a QObject as arguments.
Here's the reduced code:
self.mapper = QtCore.QSignalMapper()
self.timeline.finished.connect(self.mapper.map)
carrier = QtCore.QObject()
carrier.contents = (item1, item2)
self.mapper.setMapping(self.timeline, carrier)
self.portalMapper.mapped.connect(self.report)
def report(self, carrierObject):
print 'Triggered'
Unfortunately it doesn't work. I've traced the problem to the setMapping function by process of elimination.
This same scheme will work just fine if I switch out the QObject with an int. It also doesn't have anything to do with the attributes I added to the QObject - using a fresh-out-of-the-box QObject causes the same issue.
It seems like there is something going on here with this specific overload of the setMapping function. Any ideas about what the issue is here?
Thanks to #ekhumoro's suggestion to skip the QSignalMapper approach entirely and just create a custom signal. Worked like a charm.
I often find myself in a situation where I want to create a number of wx.StaticTextor some other widget in wxFormbuilder and be able to refer to these dynamically. Say i have a number of statictexts named a0 through a10
How would I go about finding them in code?
One way is to do a list with all the variables in, but it is ugly, and feels inefficient? Maybe not but atleast the code gets cluttered with long lists everywhere.
def updateLabels(self, data):
guiLabels = [self.a0, self.a1, self.a2 ..... ]
for i in range(len(guiLabels)):
guiLabels[i].SetLabel(data[i)
How do you go about fixing this?
Another alternative is to make the guiLabels list when initiating the app. However, I've had some problems with finding them. you have to call GetChildren() on the top window and set a different wx.ID for every StaticText and then go through every element and find this ID you made.. And the formatting when I do this is really off key.. The text gets different background colors and doesnt respect it's alignments and other funky stuff.
Any thoughts on how I can do this?
maybe something like this could work for you:
for x in xrange(10):
name = "a%s" % x # dynamically generating reference names
obj = getattr(self, name) # getting the object reference from the parent object
obj.SetLabel("xyz")
I've written a Python program and I need to toggle a group of tkinter widgets from enabled to disabled and back again. I could do it like this...
deadparrotlabel.config(state=DISABLED)
sillywalkslabel.config(state=DISABLED)
vikingslabel.config(state=DISABLED)
dinsdalelabel.config(state=DISABLED)
antpoetrylabel.config(state=DISABLED)
lumberjacklabel.config(state=DISABLED)
nudgenudgelabel.config(state=DISABLED)
saynomorelabel.config(state=DISABLED)
crunchyfroglabel.config(state=DISABLED)
larksvomitlabel.config(state=DISABLED)
but I get the feeling there should be a more efficient way, with a for loop and a list or something. I just don't know how to get it to work or even if it can be done. This is what I tried but it didn't work:
labellist = ['deadparrotlabel', 'sillywalkslabel', 'vikingslabel', 'dinsdalelabel', 'antpoetrylabel', 'lumberjacklabel', 'nudgenudgelabel', 'saynomorelabel', 'crunchyfroglabel', 'larksvomitlabel']
for i in lablelist:
i.config(state=DISABLED)
Python interprets 'i' as a string instead of the name of an object. Am I trying to do the impossible?
You can make a list of the widgets themselves:
widgets = [deadparrotlabel, sillywalkslabel, ... ]
for w in widgets:
w.config(state=DISABLED)
I think Ned's is the correct answer, however, in general, if you really do have a string, and not an object that can be used, then:
widgets = ['a', 'b', 'c']
for w in widgets:
globals()[w].config(state=DISABLED)
But then, be very wary if you find a need for this - as something has most likely gone wrong in your design process...
On an aside - perhaps locals() would be better - but difficult to tell...
I have a QVBoxLayout that I've added a few widgets to, via addWidget(). I need to now delete those widgets, and it seems I need to use removeWidget() (which takes in a widget to be removed) to do that.
I thought that calling children() or findChildren(QWidget) on my layout would return a list of the widgets I've added into it; I'm in the debugger, though, and am just receiving empty lists.
Am I terribly misunderstanding something? I've just started doing PyQT this last week and have mostly been learning through trial and error with the API docs.
To get a widget from a QLayout, you have to call its itemAt(index) method.
As the name of this method implies, it will return an item instead of a widget. Calling widget() on the result will finally give you the widget:
myWidget = self.myLayout.itemAt(index).widget()
To remove a widget, set the parent widget to None:
myWidget.setParent(None)
Also really helpfull is the QLayout count() method. To find and delete all contents of a layout:
index = myLayout.count()
while(index >= 0):
myWidget = myLayout.itemAt(index).widget()
myWidget.setParent(None)
index -=1
That's odd. My understanding is that adding widgets via addWidget transfers ownership to the layout so calling children() ought to work.
However, as an alternative you could loop over the layout items by using count() and itemAt(int) to supply a QLayoutItem to removeItem(QLayoutItem*).
Edit:
I've just tried addWidget with a straight C++ test app. and it doesn't transfer QObject ownership to the layout so children() is indeed an empty list. The docs clearly say that ownership is transferred though...
Edit 2:
Okay, it looks as though it transfers ownership to the widget that has that layout (which is not what the docs said). That makes the items in the layout siblings of the layout itself in the QObject hierarchy! It's therefore easier to stick with count and itemAt.