Compose a PyQt5 UI from multiple classes - python

I have an UI designed in QT Designer. It is formed from three tabs:
1 - Test; 2 - Train Haar; 3 - Train Hog;
In every tabs I have some buttons, or some lines, or some widgets, but when I create the code to add functions to those buttons or widgets I want to have 3 classes for every tabs, one class only for first tab, one class only for second tab and so on..
And a fourth class who call all three classes and compose my UI. I do not know how to do this, I need every classes to inherit from QMainWindow? I need to setupUi in every class?
This is my current code:
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from Qt_designer_UI import Ui_MainWindow
class Test(QtWidgets.QMainWindow):
def __init__(self):
super(Test, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
class Train_Haar(QtWidgets.QMainWindow):
def __init__(self):
super(Train_Haar, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
class Train_HOG(QtWidgets.QMainWindow):
def __init__(self):
super(Train_HOG, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
class Compose_UI(QtWidgets.QMainWindow):
def __init__(self):
super(Compose_UI, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
Test()
Train_Haar()
Train_HOG
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Compose_UI()
window.show()
sys.exit(app.exec_())

I need every classes to inherit from QMainWindow?
No, it is not necessary since it is a widget that will be inside the tabs, and that widget can be of any type.
I need to setupUi in every class?
It is only obligatory to call setupUi if you use a generated class with the help of pyuic and Qt Designer, in your case the widgets that are in each tab are generated with Qt Designer? I see that I do not
Keeping in mind that your .ui is
a possible solution is:
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from Qt_designer_UI import Ui_MainWindow
class Test(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Test, self).__init__(parent)
# for testing
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(QtWidgets.QPushButton("Test"))
class Train_Haar(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Train_Haar, self).__init__(parent)
# for testing
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(QtWidgets.QPushButton("Train_Haar"))
class Train_HOG(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Train_HOG, self).__init__(parent)
# for testing
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(QtWidgets.QPushButton("Train_HOG"))
class Compose_UI(QtWidgets.QMainWindow):
def __init__(self):
super(Compose_UI, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
test = Test()
train_haar = Train_Haar()
train_hog = Train_HOG()
for w, tab in zip(
(test, train_haar, train_hog), (self.ui.tab1, self.ui.tab2, self.ui.tab3)
):
lay = QtWidgets.QVBoxLayout(tab)
lay.addWidget(w)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = Compose_UI()
window.show()
sys.exit(app.exec_())

Related

QStackedWidget Window Communication

I Have a main.py file and two QMainWindow.py files as well. When a PushButton is clicked on the second QMainWindow.py file it should open a first QStackedWidget, and on the first QStackedWidget when a PushButton is clicked it should show a second QStackedWidget window.
main.py
from PyQt5 import QtWidgets, QtCore
from mainmenu import MainWindow
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
sys.exit(app.exec_())
mainMenu.py
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.Reg_Emp_Button.clicked.connect(self.manage_reg_Employees)
self.ui.Report_Button.clicked.connect(self.Employee_Report)
def manage_reg_Employees(self):
self.hide()
self.employeeWindow = EmployeeWindow(self)
self.employeeWindow.show()
def Employee_Report(self):
self.hide()
self.chartWindow = ChartWindow(self)
self.chartWindow.show()
ManageEmployee.py
class EmployeeWindow(QtWidgets.QMainWindow):
def __init__(self, mainMenu):
super(EmployeeWindow, self).__init__()
self.mainMenu = mainMenu
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.Back_Button.clicked.connect(self.Back_To_MainMenu)
self.ui.Add_Employee_Button_2.clicked.connect(self.Add_New_Employee)
def Back_To_MainMenu(self):
self.hide()
self.mainMenu.show()

How to change PushButton border radius

I want to change border radius of my PushButton lesson1
Tried to create a class Button with setStyleSheet in __init__ and create an object.
import sys
from pyto import *
from PyQt5 import QtCore, QtGui, QtWidgets
class MyWin(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.lesson1 = Button()
class Button(QtWidgets.QPushButton):
def __init__(self, parent = None):
super(Button, self).__init__(parent)
self.setStyleSheet('border-radius: 15px;')
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
myapp = MyWin()
myapp.show()
sys.exit(app.exec_())
No errors, but setStyleSheet doesn't work.
The code self.ui.lesson1 = Button() does not replace the self.ui.lesson1 created by Qt Designer, it only causes the new Button() to be assigned to the name self.ui.lesson1. So if you want to set the stylesheet it is not necessary to create another class:
# ...
class MyWin(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# self.ui.lesson1 = Button()
self.ui.lesson1.setStyleSheet('border-radius: 15px; background-color: red;')
# ...
I have added the background color to make the radius visible.

Add more than one Qmenu from other classes in MainWindow

I want a single menubar in my main window and be able to set the menus in the menubar from additional classes. Using the setMenuWidget command will overwrite the first menu option as shown in the code. In the classes where I set up the menu I think I may need to just set up a menu rather than a menubar, then set up the menubar in the main window.
This is what I would l like, which can be achieved by populating a single menubar in a class, though I am trying to avoid this method.
Instead only the second menu is show
import sys
from PyQt5.QtWidgets import QAction, QApplication, QMainWindow
from PyQt5 import QtCore, QtGui, QtWidgets
class ToolBar0(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self)
bar = self.menuBar() # don't think I need a menubar here
file_menu = bar.addMenu('menu1')
one = QAction('one', self)
two = QAction('two', self)
file_menu.addAction(one)
file_menu.addAction(two)
class ToolBar1(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self)
bar = self.menuBar() # don't think I need a menubar here
file_menu = bar.addMenu('menu2')
one = QAction('one', self)
two = QAction('two', self)
file_menu.addAction(one)
file_menu.addAction(two)
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self, parent=None)
#should a menubar be set up here?
#For seting widgets in main window
self.Tool_Bar0 = ToolBar0(self)
self.setMenuWidget(self.Tool_Bar0)
###menu_bar0 is over written
self.Tool_Bar1 = ToolBar1(self)
#self.setMenuWidget(self.Tool_Bar1)
if __name__ == '__main__':
app = QApplication(sys.argv)
# creating main window
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
You could use a base class with a method to return either a list of QMenu items containing QAction items or a list of QAction items and then render them in your QMainWindow toolbar in whichever way you want, here is an example:
import sys
from PyQt5.QtWidgets import QAction, QApplication, QMainWindow, QMenu
class WindowWithToolbar:
def __init__(self):
super().__init__()
def menu_items(self)->list:
pass
class Window1(WindowWithToolbar, QMainWindow):
def __init__(self):
WindowWithToolbar.__init__(self)
QMainWindow.__init__(self)
# New menu with actions
self.menu = QMenu('one')
self.menu.addActions([QAction('two', self), QAction('three', self)])
def menu_items(self):
return [self.menu]
class Window2(WindowWithToolbar, QMainWindow):
def __init__(self):
WindowWithToolbar.__init__(self)
QMainWindow.__init__(self)
def menu_items(self):
# Only actions
return [QAction('three', self), QAction('four', self)]
class MainWindow(WindowWithToolbar, QMainWindow):
def __init__(self):
QMainWindow.__init__(self, parent=None)
self.window1 = Window1()
self.window2 = Window2()
self.menu = QMenu('File')
self.helloAction = QAction('Hello')
self.menu.addAction(self.helloAction)
self._build_menu()
def menu_items(self)->list:
return [self.menu]
def _build_menu(self):
self._add_menu_items(self)
self._add_menu_items(self.window1)
self._add_menu_items(self.window2)
def _add_menu_items(self, windowWithToolbar: WindowWithToolbar):
for menu_item in windowWithToolbar.menu_items():
if isinstance(menu_item, QMenu):
self.menuBar().addMenu(menu_item)
elif isinstance(menu_item, QAction):
self.menuBar().addAction(menu_item)
if __name__ == '__main__':
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())

Trouble with PyQt4 List Widget

So my problem is the following:
I have a program that I created in QT Designer and added some code in Python.
There is an main window and two windows wich appear when you click an button in the window before.
The List Widget is in the second window:
Hope with this picture you can understand what I mean
So now I want to add some Items to my list widget.
def add_number_to_list(self):
self.ui.list_of_numbers.addItem('test')
So I call this function on another place but it didn't happen anything.
If I add an print command, to test if the function works: The print is showed. But nothing appears in the list widget...
What is wrong?
import sys
from PyQt4 import QtGui
import p_design, p_edit_numbers, p_add_number
number_to_add = ''
class Example(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = p_design.Ui_MainWindow()
self.ui.setupUi(self)
self.ui.manually_alarm.clicked.connect(self.alarm)
self.ui.edit_numbers.clicked.connect(self.open_edit_numbers)
def alarm(t1,t2):
#send sms to numbers
print('ALARM!')
def open_edit_numbers(self):
self.test = EditNumbers(self)
self.test.show()
class EditNumbers(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = p_edit_numbers.Ui_MainWindow()
self.ui.setupUi(self)
self.ui.add_number.clicked.connect(self.open_add_number)
### Problem! ###
def add_number_to_list(self):
self.ui.list_of_numbers.addItems('test')
################
def open_add_number(self):
self.t3 = AddNumber(self)
self.t3.show()
class AddNumber(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = p_add_number.Ui_MainWindow()
self.ui.setupUi(self)
self.ui.add.clicked.connect(self.add_number)
def add_number(self):
global number_to_add
editnumbers=EditNumbers()
editnumbers.add_number_to_list()
def main():
app = QtGui.QApplication(sys.argv)
form = Example()
form.show()
sys.exit(app.exec_())
main()

PyQt: How to add new tabs to QTextEdit?

I need to add a new tab, but I am having problems. I want to add new tabs in the main window, and keep the methods of the class Editor(). I can do this without having to create the class Editor() but need it to be so. Sorry for my English.
This is my code:
from PyQt4 import QtGui
from PyQt4 import QtCore
class Main(QtGui.QMainWindow):
def __init__(self):
super(Main, self).__init__()
self.initUi()
def initUi(self):
self.setWindowTitle("Editor")
self.resize(640, 480)
self.edit = Editor()
newAc = QtGui.QAction('New', self)
newAc.setShortcut('Ctrl+N')
newAc.triggered.connect(self.new_)
menu = self.menuBar()
filemenu = menu.addMenu('&File')
filemenu.addAction(newAc)
self.tab = QtGui.QTabWidget(self)
self.setCentralWidget(self.tab)
class Editor(QtGui.QTextEdit):
def __init__(self, parent=None):
super(Editor, self).__init__(parent)
def new_(self):
tab = QtGui.QTextEdit(self.tab)
self.tab.addTab(tab, 'Untitled')
def main():
import sys
app = QtGui.QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
If you want to have the same text on both (or more) tabs you can use the same Editor class, but if not, you need instantiate an Editor object for each tab.
Also your code have some problems:
1- You are handling the tabs inside Editor objects. Instead, you must handle tabs at Main level.
2- The "default" tab you're adding when you create the Main object do not have any related QTextEdit change:
self.tab = QtGui.QTabWidget(self)
self.setCentralWidget(self.tab) # <---- tab without QTextEdit
add this:
self.tab = QtGui.QTabWidget(self)
self.editor = Editor(self.tab) # editor receives self.tab widget as parent.
self.setCentralWidget(self.tab)
also you will need define Editor class before Main.
3- Main object don't have any method called new_, Editor does. So the line:
newAc.triggered.connect(self.new_)
it's wrong.
So your code might look like:
from PyQt4 import QtGui
from PyQt4 import QtCore
class Editor(QtGui.QTextEdit):
def __init__(self, parent=None):
super(Editor, self).__init__(parent)
class Main(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.initUi()
def initUi(self):
self.setWindowTitle("Editor")
self.resize(640, 480)
newAc = QtGui.QAction('New', self)
newAc.setShortcut('Ctrl+N')
newAc.triggered.connect(self.new_)
menu = self.menuBar()
filemenu = menu.addMenu('&File')
filemenu.addAction(newAc)
self.tab = QtGui.QTabWidget(self)
self.setCentralWidget(self.tab)
self.tab.addTab(Editor(), "New Text")
def new_(self):
self.tab.addTab(Editor(), "New text")
def main():
import sys
app = QtGui.QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Categories