英文:
PyQt/ PySide control widgets' actions from diffreent class or file
问题
我理解你的请求,以下是翻译好的部分:
我正在进行一个GUI项目,最初是作为简单的项目开始的,但现在规模逐渐增大。因此,我已经创建了多个类和多个文件,以使代码更容易理解。
我想要的是每个类在点击特定按钮或小部件时执行特定任务。
这是我使用QDesigner创建的简单应用程序,其中包含三个按钮。
这是我正在尝试实现的代码。
#!/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)
# 将此操作命令放在__init__方法中不起作用
self.btn2.clicked.connect(self.on_click_btn2) # <-- 这不起作用
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):
"""从父类调用此函数可行"""
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()
我的问题是为什么我无法从子类的__init__方法执行任何操作?
这是ui_main.py文件的内容,使用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"))
希望这对你有所帮助。
英文:
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.
答案1
得分: 1
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))
...
...
英文:
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))
...
...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论