2

I am developing a small user interface for a home-project. I created a *.ui file with QT-Designer. This is my main window with some navigations buttons, labels and so on. Now I am struggeling to load another *.ui (for example with content) in the frame or widget of the main window when I click on navgation buttons. I am using pyqt4 and I have to implement it with python on an raspberry pi.

I also used the search but I did not find an working solution for my problem. Maybe it is really easy but for me it is difficultly.

*Important: I don't want to reorganize buttons and labels! I want to load a whole *.ui file in a widget or frame which is in the main window!

Here my code examples: The following is my main.py

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.uic import *

def buttonKlick1close():
start.close()

start = loadUi("start.ui")
start.connect(start.pushButton, SIGNAL("clicked()") , buttonKlick1close)

# there are other "signal-connections" for my navigation buttons but I 
# integreated all exactly the same like above. 
# actually when I click to another navigation button it will open an "def" 
# with "window2.showFullscreen()" and so on.... 

start.showFullScreen()
app.exit(app.exec_())

Now, when I click on my navagtion buttons it will always open 7-8 windows and so I also need my whole navgation buttons on every window. My aim is to create ONE window with my navigation buttons and an frame/widget in it where I can promote/load the other *ui files. Or is there another good solution without frames/widgets?

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Martin Wo
  • 33
  • 1
  • 5
  • Have you tried setting a layout inside the container frame? If you set the VBox or HBoxLayout inside your container frame, you can then load the other ui and insert it as a child of the layout. – Clement Osei Tano Dec 22 '18 at 20:54
  • Hello, I didn't tried setting a layout inside the container frame, because I don't know how. I read something about the Vbox and HBoxLayout and don't know how to load the new ui file in it. Here are some code examples: I use one .py file for my whole program. Then I created 7-8 *ui files with qtDesginer. In my .py program I load the start.ui file with "show" code. In this ui file there are some navigation buttons and the main space for the frame/widget in which I want to load the other ui files. – Martin Wo Dec 23 '18 at 20:17
  • Now I have several .ui files and each .ui files has the whole navigations buttons. But I want to eliminate that solution because when I have to add or change something in the navigation I have to change on every .ui file. -> My aim is to load just one main.ui with all navigation button and one frame/widget in it, where I can load the content of the other .ui files. How can I load antoher .ui in the main.ui frame/widget?If it's still unclear I can upload a scheme. – Martin Wo Dec 25 '18 at 23:33
  • I didn't test it yet. Will try tomorrow because of holidays. But seems very good for first look!! – Martin Wo Dec 27 '18 at 00:07
  • @eyllanesc I checked your solution. It works as expected! There was a little change in main.py necessary (__file__) to-> ("__file__"). But overall perfect solution for my project. I will integrate it in my app and I hope I get access to all buttons and labels inside the ui-widgets and back. I will send donation after. Thanks a lot! – Martin Wo Dec 27 '18 at 19:16
  • @eyllanesc I am integrating my ui to your new stackedwidget-ui. Works well! But there is one more problem: How can I get access from main.py to a new integrated label on main.ui? main.label1.setText("mytext") does not work anymore because "main" does not exit. You defined main.ui at the beginning with Form, Base .....I loaded ui in the past with main = loadUi(main.ui). Can you help me? And btw: How to get acces from statuspage.py to label1 on main.ui? – Martin Wo Dec 28 '18 at 00:25
  • @eyllanesc Okay thanks! Sent you donation! Good job! – Martin Wo Dec 28 '18 at 14:12

1 Answers1

13

First of all, the basis of my solution is the promotion of a widget, for this I will structure the project in the following way:

├── main.py
├── pages
│   ├── energypage.py
│   ├── fanpage.py
│   ├── homepage.py
│   └── statuspage.py
└── ui
    ├── energy.ui
    ├── fan.ui
    ├── home.ui
    ├── main.ui
    └── status.ui

the .ui of the pages will be based on the Widget template but the main one will use the MainWindow template (MainWindow allows to have ToolBars, StatusBar, DockWidgets, menuBar, etc so I choose it as main).

Since the .ui can not be promoted by itself will create classes that invoke the design and follow a similar structure but you can add more functionalities, for example in the case of homepage.py:

import os
from PyQt4 import QtGui, uic


current_dir = os.path.dirname(os.path.abspath(__file__))
Form, Base = uic.loadUiType(os.path.join(current_dir, "../ui/home.ui"))


class HomeWidget(Base, Form):
    def __init__(self, parent=None):
        super(self.__class__, self).__init__(parent)
        self.setupUi(self)


if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    w = HomeWidget()
    w.show()
    sys.exit(app.exec_())

The main.ui has the buttons on the left side and the QStackedWidget on the right side:

enter image description here

enter image description here

Each page was added by selecting the option insert page-> after current page of the menu that opens by right clicking on the QStackedWidget

Then it will be promoted to use the widget that is in the pages folder:

enter image description here

Then in the main you associate the buttons with the appropriate indexes:

main.py

import os
from PyQt4 import QtGui, uic
from functools import partial

current_dir = os.path.dirname(os.path.abspath(__file__))
Form, Base = uic.loadUiType(os.path.join(current_dir, "ui/main.ui"))

class MainWidget(Base, Form):
    def __init__(self, parent=None):
        super(self.__class__, self).__init__(parent)
        self.setupUi(self)
        buttons = (self.homebutton, self.statusbutton, self.fanbutton, self.energybutton)
        for i, button in enumerate(buttons):
            button.clicked.connect(partial(self.stackedWidget.setCurrentIndex, i))

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    app.setStyle("fusion")
    w = MainWidget()
    w.show()
    sys.exit(app.exec_())

The complete example is here.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • This is all fantastic, but how would you for example use LineEdit value from the module "Status" in the module "Fan"? – Kokokoko May 31 '22 at 12:27