I think the problems you are having are related to the approach you are taking to swap the UIs. What you might find to work much better is to design your modular UIs as complete widgets, and your static method (factory method) would return a new instance of the widget.
Instead of trying to set a new layout against the parent and clearing out children, go the other way around. Let the module UIs know nothing of their parents. They are just widgets. Instead, your main UI does the job of taking that new widget instance, and setting it into some container. When the selection changes, you can just delete that single widget, then add a new one.
There are a number of ready-made solutions that can act as your container:
With the former 2, you would just set a single widget into the container. Then retrieve it, deleteLater, and set a new one into the first position.
Generically, it may look something like this:
class MyMainUI:
stackedLayout
def setCurrentWidget
stackLayout.currentWidget.deleteLater()
newWidget = ModularUI()
stackLayout.addWidget(newWidget)
ModularUI(QWidget):
layout
label
text
buttons
Really, when I look at the code examples, it seems like you don't even really need the factory method, since its just acting the exact same as a constructor.