问题描述
我最近开始学习 Python + PyQt5。请帮助我理解如何在python中的另一个类中调用类函数。
from PyQt5 import QtGui,QtWidgets,QtCore,uic
from PyQt5.Qt import *
class mywindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
QtWidgets.QMainWindow.__init__(self)
self.ui = uic.loadUi('test.ui',self)
self.resize(820,300)
self.setFixedSize(self.size())
self.pushButton.clicked.connect(self.getValue)
self.thread = {}
self.pushButtonStart.clicked.connect(self.start_worker_1)
self.pushButtonStop.clicked.connect(self.stop_worker_1)
def getValue(self):
self.value = self.spinBox.value()
i = 1
while i <= self.value:
os.system('test1.py')
i += 1
else:
print('End,i =',i)
def start_worker_1(self):
self.thread[1] = ThreadClass(parent=None,index=1)
self.thread[1].start()
self.pushButtonStart.setEnabled(False)
self.pushButtonStop.setEnabled(True)
def stop_worker_1(self):
self.thread[1].stop()
self.pushButtonStart.setEnabled(True)
self.pushButtonStop.setEnabled(False)
class ThreadClass(QtCore.QThread):
any_signal = QtCore.pyqtSignal(int)
def __init__(self,parent=None,index=0):
super(ThreadClass,self).__init__(parent)
self.index = index
self.is_running = True
def run(self):
print('Start...',self.index)
a = mywindow()
a.getValue()
def stop(self):
self.is_running = False
print('Stop...',self.index)
self.terminate()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
application = mywindow()
application.show()
sys.exit(app.exec())
我需要按照 spinBox 中指定的次数执行 test.py 文件
Start... 1
End,i = 1
如果我在 while i <= 4:
时这样做,那么它会起作用。但是如果我从 SpinBox 传递 self.value 就不起作用。
我做错了什么?
解决方法
您不必要地使您的应用程序复杂化,此外您还遇到了在每个线程中创建窗口对象的错误,这是不合逻辑的,而且禁止在另一个线程中创建小部件。
在这种情况下,最好使用 QProcess 和信号来了解脚本何时完成执行。
注意:由于没有提供 .ui,所以我将展示一个简单的例子:
test.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>180</width>
<height>98</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="spinBox"/>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>180</width>
<height>28</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
main.py
import os
import sys
from functools import cached_property
from pathlib import Path
from PyQt5 import QtGui,QtWidgets,QtCore,uic
CURRENT_DIRECTORY = Path(__file__).resolve().parent
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ui = uic.loadUi(os.fspath(CURRENT_DIRECTORY / "test.ui"),self)
self.ui.pushButton.clicked.connect(self.handle_clicked)
@cached_property
def manager(self):
return Manager()
def handle_clicked(self):
number_of_processes = self.ui.spinBox.value()
script = os.fspath(CURRENT_DIRECTORY / "test1.py")
for i in range(number_of_processes):
self.manager.execute(script,dict(i=i))
class Manager(QtCore.QObject):
@cached_property
def processes(self):
return list()
def execute(self,script,metadata=None):
process = QtCore.QProcess()
process.setProperty("metadata",metadata or dict())
process.finished.connect(self.handle_finished)
process.setProgram(sys.executable)
process.setArguments([script])
process.start()
self.processes.append(process)
def handle_finished(self):
process = self.sender()
self.processes.remove(process)
metadata = process.property("metadata")
print(f"{metadata} finished")
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())