Issue
I am working on a GUI project that was started as simple but growing in size now. Therefore, I have created multiple classes in multiple files to make the code easily understandable.
What I want is that each class should do specific tasks when clicking a particular button or widget.
Here is the simple app I have created using QDesigner which contains three buttons.
Here is the code I am trying to implement.
#!/bin/env python
import sys
from PyQt6 import QtWidgets
from ui_main import Ui_MainWindow
class Page2(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
# Keeping this action command within __init__ method does not work
self.btn2.clicked.connect(self.on_click_btn2) # <-- This does not work
def on_click_btn2(self):
print("Clicked Button 2")
class Page3(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
def on_click_btn3(self):
print("Clicked Button 3")
def clicks(self):
""" Calling this function from parent class works """
self.btn3.clicked.connect(self.on_click_btn3)
class MainWindow(Page2, Page3, QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
Page3.clicks(self)
self.btn1.clicked.connect(self.on_click_btn1)
def on_click_btn1(self):
print("Clicked Button 1")
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
My question is why am I not able to do any actions from child class's init method?
Here is the content of ui_main.py file that was converted using uic6
from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtWidgets import QPushButton as PushButton
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(332, 360)
self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setContentsMargins(-1, 45, -1, -1)
self.verticalLayout.setObjectName("verticalLayout")
self.btn1 = PushButton(parent=self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.btn1.sizePolicy().hasHeightForWidth())
self.btn1.setSizePolicy(sizePolicy)
self.btn1.setObjectName("btn1")
self.verticalLayout.addWidget(self.btn1)
self.btn2 = PushButton(parent=self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.btn2.sizePolicy().hasHeightForWidth())
self.btn2.setSizePolicy(sizePolicy)
self.btn2.setObjectName("btn2")
self.verticalLayout.addWidget(self.btn2)
self.btn3 = PushButton(parent=self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.btn3.sizePolicy().hasHeightForWidth())
self.btn3.setSizePolicy(sizePolicy)
self.btn3.setObjectName("btn3")
self.verticalLayout.addWidget(self.btn3)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.btn1.setText(_translate("MainWindow", "Page 1"))
self.btn2.setText(_translate("MainWindow", "Page 2"))
self.btn3.setText(_translate("MainWindow", "Page 3"))
Any help is appreciated.
Solution
You should not derive the Page#
classes from the QMainWindow
because it's not a window. Also, it's a bad idea to make a widget class inherit a Ui_xxx
class generated by Qt Designer, because it breaks the information hiding principle. (What if a name of an attribute in a widget class conflicts with the name of an attribute in the corresponding Ui_xxx
class?)
So, do like this.
...
class Page2Handler:
def __init__(self, main_win):
self.main_win = main_win
def handle():
print("Clicked Button 2", self.main_win)
...
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ui = ui = Ui_MainWindow()
ui.setupUi(self)
...
self.page2handler = Page2Handler(self)
ui.btn2.clicked.connect(self.page2handler.handle)
...
...
If your page handlers do not need to maintain some kind of state, it's much simpler to do like this.
...
def handle_page2(main_win):
print("Clicked Button 2", main_win)
...
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ui = ui = Ui_MainWindow()
ui.setupUi(self)
...
ui.btn2.clicked.connect(lambda: handle_page2(self))
...
...
Answered By - relent95
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.