Hey Marcus,
I can see the value in using this tool for debugging purposes, as a
convenient way to list the absolute location of a given widget in a
meaningful way. That is, as long as all of your widgets have meaningful
names set on them.
But I am wondering, if used in non-debugging (normal production)
circumstances, does this promote poor Qt design by encouraging people to
break encapsulation between components of the Qt application? I've always
been under the impression that it should be preferable to not have objects
at higher levels reaching into subcomponents, or visa-versa child
components knowing absolute paths outside locations. What would be some of
the valid use-cases in non-debugging situations for providing this type of
behavior?
For instance with the Undo/Redo example you had given, my assumption is you
would be using this to have the command entries be able to retain an
absolute reference to teh widget for which it will want to operate on at a
later date, should that command be activated in the history stack. But
instead of storing absolute string paths based on object names and types,
would it not be more consistent and safer to store weak references to the
target widget? A weak reference will be the actual object, valid until the
source object is garbage collected, and would withstand circumstances of
the widget being reparented or deleted. It could be quite common for a
widget to be moved into a different layout or under a different parent.
Also that it is valid for two sibling objects to have the same objectName.
So which one gets resolved when it is by objectName and parent hierarchy?
class Window(QtGui.QDialog):
def __init__(self):
super(Window, self).__init__()
self.button1 = QtGui.QPushButton("Button1", self)
self.button1.setObjectName("button")
self.button2 = QtGui.QPushButton("Button2", self)
self.button2.setObjectName("button")
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button1)
layout.addWidget(self.button2)
self.button1.clicked.connect(self.me)
self.button2.clicked.connect(self.me)
def me(self):
print self.sender().objectName()# button# button
I'm just curious to know what you would consider to be valid production
usages of this tool that warrant relying on absolute widget locations in
deeply nested hierarchies.
-- justin
On Wed, Jun 4, 2014 at 6:12 AM, Marcus Ottosson <[email protected]>
wrote:
> Ah, we might be referring to separate issues.
>
> Have a look at this:
>
> class Demo(QtWidgets.QWidget):
> """
> Object hierarchy looks like this:
> Win (Demo)
> |-- Body (QWidget)
> |-- Button (QPushButton)
>
> Which translates into:
> /Win.Demo/Body.QWidget/Button.QPushButton
>
> """
>
> def __init__(self, parent=None):
> super(Demo, self).__init__(parent)
>
> body = QtWidgets.QWidget()
>
> demo_button = QtWidgets.QPushButton('Hello Demo')
> body_button = QtWidgets.QPushButton('Hello Body')
>
> layout = QtWidgets.QHBoxLayout(body)
> layout.addWidget(body_button)
>
> layout = QtWidgets.QHBoxLayout(self)
> layout.addWidget(demo_button)
> layout.addWidget(body)
>
> for widget_, name_ in {
> self: 'Win',
> body: 'Body',
> demo_button: 'Button',
> body_button: 'Button',
> }.iteritems():
> widget_.setObjectName(name_)
> if __name__ == '__main__':
> import sys
>
> # Set-up PyQt application
> app = QtWidgets.QApplication(sys.argv)
> win = Demo()
>
> # How we would normally find `Button` within `Demo`
> find_button = win.findChild(QtWidgets.QPushButton, 'Button')
>
> # Get an instance from `Demo` by serialised path
> button = qtpath.instance(win, '/Body.QWidget/Button.QPushButton')
> button = qtpath.instance(win, '/Button.QPushButton')
> assert find_button == button
>
> # Get back the serialised path from instance.
> assert qtpath.abspath(win, button) == '/Win.Demo/Button.QPushButton'
>
> # A path may return nothing
> missing = qtpath.instance(win, '/Body.QWidget/Checkbox.QWidget')
> assert missing is None
>
> # findPath searches a hierarchy, regardless of proximity to root
> # The following will return `Button` closest to `Win`, there is no
> # way to directly reference the nested `Button`.
> button = win.findChild(QtWidgets.QPushButton, 'Button')
> assert button.parent() == win
>
> button = qtpath.instance(win, '/Body.QWidget/Button.QPushButton')
> assert button is not find_button
>
> On 3 June 2014 17:19, Fredrik Averpil <[email protected]> wrote:
>
> Sure. But I was referring to what I usually do, and which could sometimes
>> be problematic and where it looks like your qtpaths solves it (I think):
>>
>> I set the parent from within a subclass with a parent like
>>
>> self.mainName = parent
>>
>> And then if this subclass is inherited I may set
>>
>> self.mainName.subclassName = parent
>>
>> And so on… and then I would make sure I can access these object names
>> throughout my app. So from any class, I can access
>> self.mainName.subclassName.widgetName
>>
>> But in the case of e.g. an image viewer which loads the same widget *n*
>> times (e.g. one per image), you can’t hard code names like that. That’s
>> where I thought your solution seemed nice, cause then you could serialize
>> on window or maybe parent widget.
>>
>> On a slightly different note… if you load ui files into PySide vs PyQt
>> the recommended ways of doing it – PySide/QUiLoader vs PyQt/uic.loadUi –
>> this results in different ways of fetching the ui widgets. I solved this
>> with by using PySide/pysideuic vs PyQT/uic, as shown in this boilerplate:
>> https://github.com/fredrikaverpil/pyVFX-boilerplate
>> I wrote more about that in detail here:
>> https://github.com/fredrikaverpil/pyVFX-boilerplate/wiki#why-pysideuic
>> Not sure if that is at all related to what you're doing but maybe worth
>> taking into account.
>>
>> // Fredrik
>>
>>
>>
>> Thanks Fredrik, I’ve also felt the need for something like this.
>>> Especially for debugging and CSS.
>>>
>>> But this could of course sometimes become problematic if a class can
>>> have different parents.
>>>
>>> Could you elaborate on this?
>>>
>>>
>>> --
>> You received this message because you are subscribed to the Google Groups
>> "Python Programming for Autodesk Maya" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/python_inside_maya/CAD%3DwhWOdn%2BAXuffvp3MX49YfCEwfuaoDVCNm_pNRH3y4LPCn9A%40mail.gmail.com
>> <https://groups.google.com/d/msgid/python_inside_maya/CAD%3DwhWOdn%2BAXuffvp3MX49YfCEwfuaoDVCNm_pNRH3y4LPCn9A%40mail.gmail.com?utm_medium=email&utm_source=footer>
>> .
>>
>> For more options, visit https://groups.google.com/d/optout.
>>
>
> --
> *Marcus Ottosson*
> [email protected]
>
> --
> You received this message because you are subscribed to the Google Groups
> "Python Programming for Autodesk Maya" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOCp_Sam8kik2ZJ4a1kE0T10KNrtjZn6RD0WC9m6OPXjxQ%40mail.gmail.com
> <https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOCp_Sam8kik2ZJ4a1kE0T10KNrtjZn6RD0WC9m6OPXjxQ%40mail.gmail.com?utm_medium=email&utm_source=footer>
> .
>
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google Groups
"Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/python_inside_maya/CAPGFgA3tdRQtkEP9Rw8jcozF6p2NW3gpuqC7AH1LUWq7N9W0Xw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.