6

I wondered if anyone could tell me is it possible to divide the following code into two python classes which will then be placed in two different files:

from GUI import mainGUI
from GUI import subwindowGUI

class MyApp(QMainWindow, mainGUI.Ui_MainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setupUi(self)

        # mainGUI contains QMdiarea in which it opens
        # a subwindow by calling a function MySubWin(self)

        # QMdiarea name is 'body'

        self.OpenSub.triggered.connect(self.MySubWin)

    def MySubWin(self):
        self.MySubWin = QWidget()
        self.MySubWin.setObjectName('Module window')

        self.myTabs = QtabWidget(self.MySubWin)
        self.myTabs.setObjectName('myTabs')

        # now I call the function that will display
        # the gui elements inside this 'Module window'
        self.create_module_gui()

        self.body.addSubWindow(self.MySubWin)
        self.MySubWin.showNormal()

    def create_module_gui(self, *args):
        module_gui = subwindowGUI.Ui_ModuleWindow()
        module_gui.setupUi(module_gui)

        self.myTabs.addTab(module_gui, _('New tab'))
        self.myTabs.setCurrentWidget(module_gui)

As you can see from the code above my functions are interacting with the main window gui elements. I wanted to move these functions that are related to this specific module into a separate file for the maintaining purposes. That's why I'm asking you to help me on how to achieve that if it's even possible. Thanks in advance, Tomislav.

@Mel:

If I for move those functions into another file:

myFunctions.py

class MyFunctions(object):

    def MySubWin(self):
        self.MySubWin = QWidget()
        self.MySubWin.setObjectName('Module window')

        self.myTabs = QtabWidget(self.MySubWin)
        self.myTabs.setObjectName('myTabs')

        # now I call the function that will display
        # the gui elements inside this 'Module window'
        self.create_module_gui()

        self.body.addSubWindow(self.MySubWin)
        self.MySubWin.showNormal()

    def create_module_gui(self, *args):
        module_gui = subwindowGUI.Ui_ModuleWindow()
        module_gui.setupUi(module_gui)

        self.myTabs.addTab(module_gui, _('New tab'))
        self.myTabs.setCurrentWidget(module_gui)

and then I import that file into my main file.

import myFunctions

class MyApp(QMainWindow, mainGUI.Ui_MainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setupUi(self)

        # mainGUI contains QMdiarea in which it opens
        # a subwindow by calling a function MySubWin(self)

        # QMdiarea name is 'body'

        self.OpenSub.triggered.connect(MyFunctions.MySubWin)

What I end up with is the error saying that MyFunctions object has no attribute body.

Beller0ph0n
  • 105
  • 1
  • 2
  • 10
  • You're already doing it with `GUI`: the code is in a different file, you import it at the beginning and then use it. You can do the same for any code. – Mel Jan 28 '16 at 11:25

2 Answers2

5

1st I must say that you won't gain any maintenance out of this ... but for example lets move the create_module_gui to another class

in a new file: creategui.py

class CreateGUI(object):
   
    def create_module_gui(self, *args):
        module_gui = subwindowGUI.Ui_ModuleWindow()
        module_gui.setupUi(module_gui)

        self.myTabs.addTab(module_gui, _('New tab'))
        self.myTabs.setCurrentWidget(module_gui)

in your code:

from GUI import mainGUI
from GUI import subwindowGUI
from creategui import CreateGUI

class MyApp(QMainWindow, mainGUI.Ui_MainWindow, CreateGUI):
     #yay you have your create_module_gui method now...

Now you can also just put create_module_gui as a function in another file and call it with self as the first param...

Community
  • 1
  • 1
Yoav Glazner
  • 7,936
  • 1
  • 19
  • 36
  • 1
    Thank you very very much Yoav. It works like a charm!! As far as the maintenance goes now it will be much easier for me to maintain my modules since I can place each module in the separate file. It's much easier to find an error in 100 lines of code than it is in a 1000+ lines of code. Once again thanks a lot. – Beller0ph0n Jan 28 '16 at 11:51
  • @Beller0ph0n - No problem, just note that is is better to make the splitting based on **SRP** and not just about lines of code – Yoav Glazner Jan 28 '16 at 11:54
  • I agree with you. Could you maybe point some guidelines or suggestions regarding SRP principle (tutorials or documentation). Thanks in advance Yoav. – Beller0ph0n Jan 28 '16 at 12:25
  • [Single-responsibility principle](https://en.wikipedia.org/wiki/Single-responsibility_principle). similar to unix philosophy: [Do One Thing and Do It Well](https://en.wikipedia.org/wiki/Unix_philosophy#Do_One_Thing_and_Do_It_Well). but only you know your program : ) – milahu Oct 15 '21 at 08:15
4

See this solution: https://stackoverflow.com/a/47562412/10155767

In your case, don't make a class in myFunctions.py. Instead, define the functions at the top level. Thus myFunctions.py should look like:

def MySubWin(self):
    ...

def create_module_gui(self, *args):
    ...

Then in your original file, import the functions within the class like

class MyApp(QMainWindow, mainGUI.Ui_MainWindow):
    from myFunctions import MySubWin, create_module_gui

    def __init__(self, parent=None):
        ...
Ben Mares
  • 1,764
  • 1
  • 15
  • 26
  • a trick to keep the indents: `if True: ...`. keeping indents is useful to reduce diff-noise, especially when contributing to someone else's project – milahu Oct 15 '21 at 08:32