PyQt/ PySide 控件小部分动作来自不同类别或文件

huangapple go评论72阅读模式
英文:

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.

PyQt/ PySide 控件小部分动作来自不同类别或文件

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))
...
...

huangapple
  • 本文由 发表于 2023年5月23日 00:40:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76308299.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定