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

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

PyQt/ PySide control widgets' actions from diffreent class or file

问题

我理解你的请求,以下是翻译好的部分:

我正在进行一个GUI项目,最初是作为简单的项目开始的,但现在规模逐渐增大。因此,我已经创建了多个类和多个文件,以使代码更容易理解。

我想要的是每个类在点击特定按钮或小部件时执行特定任务。

这是我使用QDesigner创建的简单应用程序,其中包含三个按钮。

这是我正在尝试实现的代码。

  1. #!/bin/env python
  2. import sys
  3. from PyQt6 import QtWidgets
  4. from ui_main import Ui_MainWindow
  5. class Page2(QtWidgets.QMainWindow, Ui_MainWindow):
  6. def __init__(self):
  7. super().__init__()
  8. self.setupUi(self)
  9. # 将此操作命令放在__init__方法中不起作用
  10. self.btn2.clicked.connect(self.on_click_btn2) # <-- 这不起作用
  11. def on_click_btn2(self):
  12. print("Clicked Button 2")
  13. class Page3(QtWidgets.QMainWindow, Ui_MainWindow):
  14. def __init__(self):
  15. super().__init__()
  16. self.setupUi(self)
  17. def on_click_btn3(self):
  18. print("Clicked Button 3")
  19. def clicks(self):
  20. """从父类调用此函数可行"""
  21. self.btn3.clicked.connect(self.on_click_btn3)
  22. class MainWindow(Page2, Page3, QtWidgets.QMainWindow, Ui_MainWindow):
  23. def __init__(self):
  24. super().__init__()
  25. self.setupUi(self)
  26. Page3.clicks(self)
  27. self.btn1.clicked.connect(self.on_click_btn1)
  28. def on_click_btn1(self):
  29. print("Clicked Button 1")
  30. app = QtWidgets.QApplication(sys.argv)
  31. window = MainWindow()
  32. window.show()
  33. app.exec()

我的问题是为什么我无法从子类的__init__方法执行任何操作?

这是ui_main.py文件的内容,使用uic6进行转换:

  1. from PyQt6 import QtCore, QtGui, QtWidgets
  2. from PyQt6.QtWidgets import QPushButton as PushButton
  3. class Ui_MainWindow(object):
  4. def setupUi(self, MainWindow):
  5. MainWindow.setObjectName("MainWindow")
  6. MainWindow.resize(332, 360)
  7. self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
  8. self.centralwidget.setObjectName("centralwidget")
  9. self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
  10. self.verticalLayout.setContentsMargins(-1, 45, -1, -1)
  11. self.verticalLayout.setObjectName("verticalLayout")
  12. self.btn1 = PushButton(parent=self.centralwidget)
  13. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
  14. sizePolicy.setHorizontalStretch(0)
  15. sizePolicy.setVerticalStretch(0)
  16. sizePolicy.setHeightForWidth(self.btn1.sizePolicy().hasHeightForWidth())
  17. self.btn1.setSizePolicy(sizePolicy)
  18. self.btn1.setObjectName("btn1")
  19. self.verticalLayout.addWidget(self.btn1)
  20. self.btn2 = PushButton(parent=self.centralwidget)
  21. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
  22. sizePolicy.setHorizontalStretch(0)
  23. sizePolicy.setVerticalStretch(0)
  24. sizePolicy.setHeightForWidth(self.btn2.sizePolicy().hasHeightForWidth())
  25. self.btn2.setSizePolicy(sizePolicy)
  26. self.btn2.setObjectName("btn2")
  27. self.verticalLayout.addWidget(self.btn2)
  28. self.btn3 = PushButton(parent=self.centralwidget)
  29. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
  30. sizePolicy.setHorizontalStretch(0)
  31. sizePolicy.setVerticalStretch(0)
  32. sizePolicy.setHeightForWidth(self.btn3.sizePolicy().hasHeightForWidth())
  33. self.btn3.setSizePolicy(sizePolicy)
  34. self.btn3.setObjectName("btn3")
  35. self.verticalLayout.addWidget(self.btn3)
  36. MainWindow.setCentralWidget(self.centralwidget)
  37. self.retranslateUi(MainWindow)
  38. QtCore.QMetaObject.connectSlotsByName(MainWindow)
  39. def retranslateUi(self, MainWindow):
  40. _translate = QtCore.QCoreApplication.translate
  41. MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
  42. self.btn1.setText(_translate("MainWindow", "Page 1"))
  43. self.btn2.setText(_translate("MainWindow", "Page 2"))
  44. 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.

  1. #!/bin/env python
  2. import sys
  3. from PyQt6 import QtWidgets
  4. from ui_main import Ui_MainWindow
  5. class Page2(QtWidgets.QMainWindow, Ui_MainWindow):
  6. def __init__(self):
  7. super().__init__()
  8. self.setupUi(self)
  9. # Keeping this action command within __init__ method does not work
  10. self.btn2.clicked.connect(self.on_click_btn2) # <-- This does not work
  11. def on_click_btn2(self):
  12. print("Clicked Button 2")
  13. class Page3(QtWidgets.QMainWindow, Ui_MainWindow):
  14. def __init__(self):
  15. super().__init__()
  16. self.setupUi(self)
  17. def on_click_btn3(self):
  18. print("Clicked Button 3")
  19. def clicks(self):
  20. """ Calling this function from parent class works """
  21. self.btn3.clicked.connect(self.on_click_btn3)
  22. class MainWindow(Page2, Page3, QtWidgets.QMainWindow, Ui_MainWindow):
  23. def __init__(self):
  24. super().__init__()
  25. self.setupUi(self)
  26. Page3.clicks(self)
  27. self.btn1.clicked.connect(self.on_click_btn1)
  28. def on_click_btn1(self):
  29. print("Clicked Button 1")
  30. app = QtWidgets.QApplication(sys.argv)
  31. window = MainWindow()
  32. window.show()
  33. 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

  1. from PyQt6 import QtCore, QtGui, QtWidgets
  2. from PyQt6.QtWidgets import QPushButton as PushButton
  3. class Ui_MainWindow(object):
  4. def setupUi(self, MainWindow):
  5. MainWindow.setObjectName("MainWindow")
  6. MainWindow.resize(332, 360)
  7. self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
  8. self.centralwidget.setObjectName("centralwidget")
  9. self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
  10. self.verticalLayout.setContentsMargins(-1, 45, -1, -1)
  11. self.verticalLayout.setObjectName("verticalLayout")
  12. self.btn1 = PushButton(parent=self.centralwidget)
  13. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
  14. sizePolicy.setHorizontalStretch(0)
  15. sizePolicy.setVerticalStretch(0)
  16. sizePolicy.setHeightForWidth(self.btn1.sizePolicy().hasHeightForWidth())
  17. self.btn1.setSizePolicy(sizePolicy)
  18. self.btn1.setObjectName("btn1")
  19. self.verticalLayout.addWidget(self.btn1)
  20. self.btn2 = PushButton(parent=self.centralwidget)
  21. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
  22. sizePolicy.setHorizontalStretch(0)
  23. sizePolicy.setVerticalStretch(0)
  24. sizePolicy.setHeightForWidth(self.btn2.sizePolicy().hasHeightForWidth())
  25. self.btn2.setSizePolicy(sizePolicy)
  26. self.btn2.setObjectName("btn2")
  27. self.verticalLayout.addWidget(self.btn2)
  28. self.btn3 = PushButton(parent=self.centralwidget)
  29. sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
  30. sizePolicy.setHorizontalStretch(0)
  31. sizePolicy.setVerticalStretch(0)
  32. sizePolicy.setHeightForWidth(self.btn3.sizePolicy().hasHeightForWidth())
  33. self.btn3.setSizePolicy(sizePolicy)
  34. self.btn3.setObjectName("btn3")
  35. self.verticalLayout.addWidget(self.btn3)
  36. MainWindow.setCentralWidget(self.centralwidget)
  37. self.retranslateUi(MainWindow)
  38. QtCore.QMetaObject.connectSlotsByName(MainWindow)
  39. def retranslateUi(self, MainWindow):
  40. _translate = QtCore.QCoreApplication.translate
  41. MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
  42. self.btn1.setText(_translate("MainWindow", "Page 1"))
  43. self.btn2.setText(_translate("MainWindow", "Page 2"))
  44. 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.

  1. ...
  2. class Page2Handler:
  3. def __init__(self, main_win):
  4. self.main_win = main_win
  5. def handle():
  6. print("Clicked Button 2", self.main_win)
  7. ...
  8. class MainWindow(QtWidgets.QMainWindow):
  9. def __init__(self):
  10. super().__init__()
  11. self.ui = ui = Ui_MainWindow()
  12. ui.setupUi(self)
  13. ...
  14. self.page2handler = Page2Handler(self)
  15. ui.btn2.clicked.connect(self.page2handler.handle)
  16. ...
  17. ...

If your page handlers do not need to maintain some kind of state, it's much simpler to do like this.

  1. ...
  2. def handle_page2(main_win):
  3. print("Clicked Button 2", main_win)
  4. ...
  5. class MainWindow(QtWidgets.QMainWindow):
  6. def __init__(self):
  7. super().__init__()
  8. self.ui = ui = Ui_MainWindow()
  9. ui.setupUi(self)
  10. ...
  11. ui.btn2.clicked.connect(lambda: handle_page2(self))
  12. ...
  13. ...
英文:

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.

  1. ...
  2. class Page2Handler:
  3. def __init__(self, main_win):
  4. self.main_win = main_win
  5. def handle():
  6. print("Clicked Button 2", self.main_win)
  7. ...
  8. class MainWindow(QtWidgets.QMainWindow):
  9. def __init__(self):
  10. super().__init__()
  11. self.ui = ui = Ui_MainWindow()
  12. ui.setupUi(self)
  13. ...
  14. self.page2handler = Page2Handler(self)
  15. ui.btn2.clicked.connect(self.page2handler.handle)
  16. ...
  17. ...

If your page handlers do not need to maintain some kind of state, it's much simpler to do like this.

  1. ...
  2. def handle_page2(main_win):
  3. print("Clicked Button 2", main_win)
  4. ...
  5. class MainWindow(QtWidgets.QMainWindow):
  6. def __init__(self):
  7. super().__init__()
  8. self.ui = ui = Ui_MainWindow()
  9. ui.setupUi(self)
  10. ...
  11. ui.btn2.clicked.connect(lambda: handle_page2(self))
  12. ...
  13. ...

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:

确定