4

I have the following problem with my pyqt:

Assuming i create an object within the Qt Designer and save it as an .ui file. Then i use pyuic to convert it to an .py file. Because i want to integrate a new module into a given program, this is the favorite way to go (because later the .ui files will be converted automatically at startup to .py files).

If i have a look at my .py file i see the following for the window:

class Ui_SubWindow(object):
    def setupUi(self, SubWindow):
        SubWindow.setObjectName(_fromUtf8("SubWindow"))
        ....

i have a RemoteWindow class as MainWindow where the SubWindow is initiated:

class RemoteWindow(QtGui.QMainWindow):
  def __init__(self, subcore):
    super(RemoteWindow, self).__init__(subcore.core.gui)
    self.subcore = subcore
    self.ui = Ui_SubWindow()

Now i have a core program:

class SubCore(object):
  def __init__(self, core, identity, number):
    ...
    self.gui = RemoteWindow(self)
    self.newController = NewController(self.gui)

and the new controller class:

class NewController(object):
  def __init__(self, subwindow):
    self.subwindow = subwindow
    self.ui = subwindow.ui

from my controller i want to call a .findChild() on that window

submitFrame = self.ui.findChild(QtGui.QFrame, "frameSubmit")

, but all i get is an:

AttributeError: 'Ui_SubWindow' object has no attribute 'findChild'

I assume this is, because the class Ui_SubWindow is not a child class of some QObject but of an object, am i right?

self.ui is the same as subwindow.ui, where subwindow is an instance of RemoteWindow which has as .ui argument the Ui_SubWindow Class.

Is there any chance to make the pyuic or the Qt Designer to make this SubWindow a child of QObject, without manipulating the automatically generated .py file?

fighter-ii
  • 479
  • 2
  • 6
  • 19

3 Answers3

4

You don't need to use findChild at all, because pyuic will automatically create attributes in the ui object for all the widgets defined in Qt Designer. The attribute names are taken from the objectName. So all you need is:

submitFrame = self.ui.frameSubmit
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • 1
    I want do use findChild, because i later add items dynamically (with a for loop, so 1 to n objects, identiyable by name "element_" + str(i) and want to access them via object name – fighter-ii Nov 07 '17 at 16:55
  • 1
    @fighter-ii. Your question specifically asks about widgets created in Qt Designer. For that, the solution I gave is by far the best. It will work for **all** objects, not just subclasses of `QObject`; it does not require the objects to have a parent; and even if they do have a parent, there's no need to know what the parent is. That is why pyuic is designed to work the way it does. For dynamically generated widgets, it is much better to use a list: i.e. `self.ui.element[i]`. The `findChild` method has its uses, but it is not a good general solution. – ekhumoro Nov 07 '17 at 17:31
  • Thank you for your input. In fact i just wrapped a frame around the dynamically generated inputs (and also added this frame in Qt Designer), so now i can acces/delete the whole frame and can build it up manually if i need to. – fighter-ii Nov 08 '17 at 07:29
3

Qt Designer creates a design, that is, a class that serves to fill the main widget so the internal widgets are not children of this class, if you want to use findChild you must do it to the widget that returns this class after calling the method setupUi.

class RemoteWindow(QtGui.QMainWindow):
  def __init__(self, subcore):
    super(RemoteWindow, self).__init__(subcore.core.gui)
    self.subcore = subcore
    self.ui = Ui_SubWindow()
    self.ui.setupUi(self) # Here the widget is filled
    [...]

And then you should use it in the following way:

class NewController(object):
  def __init__(self, subwindow):
    self.subwindow = subwindow
    submitFrame = self.subwindow.findChild(QtGui.QFrame, "frameSubmit")
    [...]
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • I chosed your answer as accepted answer, because calling findChild on self.subwindow instead of self.ui did the trick. Thank you! – fighter-ii Nov 08 '17 at 07:30
0

I recently had to do this same thing and leaving this here in case someone sees this link vs the other related one. https://stackoverflow.com/a/62340205/1621381

for name, obj in dict(self.__dict__).items():
        # print(str(name) + str(obj))
        obj_type = str(obj).strip("<PyQt5").rsplit(" ")[0].replace(".", '', 1)
        # obj_type = str(obj).strip("<").rsplit(" ")[0]
        # print(obj_type)
        # obj_type = obj_str.strip("<PyQt5").rsplit(" ")[0].replace(".", '', 1)
        label_name = "self." + str(name)
        try:
            label_name = self.findChild(eval(obj_type), name)
            print(str(label_name) + ' created')
        except:
            pass
        if not isinstance(obj_type, QObject):
            continue
Mike R
  • 679
  • 7
  • 13