Python 使用QThreads的正确方法是什么?
我正在尝试使用PySide构建一个具有多个窗口的Python应用程序。每个窗口执行一些函数,一个函数的执行不应该阻止其他窗口执行它们自己的函数,这就是为什么我需要使用多线程。但是我不知道怎么做。我尝试使用新方法来使用线程(正确的一个),但是我在网上找到的所有例子都是C++的,我对C++一无所知,这就是我请求帮助的原因。 为了简化起见,我构建了两个模块,一个名为Python 使用QThreads的正确方法是什么?,python,multithreading,pyside,qthread,Python,Multithreading,Pyside,Qthread,我正在尝试使用PySide构建一个具有多个窗口的Python应用程序。每个窗口执行一些函数,一个函数的执行不应该阻止其他窗口执行它们自己的函数,这就是为什么我需要使用多线程。但是我不知道怎么做。我尝试使用新方法来使用线程(正确的一个),但是我在网上找到的所有例子都是C++的,我对C++一无所知,这就是我请求帮助的原因。 为了简化起见,我构建了两个模块,一个名为test\u main,另一个名为test\u wdw 这是test\u main的代码: import sys import test_
test\u main
,另一个名为test\u wdw
这是test\u main
的代码:
import sys
import test_wdw
from PySide import QtGui
from PySide import QtCore
class Main_Window(QtGui.QMainWindow):
def __init__(self):
super(Main_Window,self).__init__()
self.initUI()
def initUI(self):
self.statusBar()
self.new_window=QtGui.QAction("&Window alpha",self)
self.new_window.triggered.connect(self.open_window)
self.menu_bar=self.menuBar()
self.menu1=self.menu_bar.addMenu('&Menu 1')
self.menu1.addAction(self.new_window)
# Creates a QMdiArea to manage all windows
self.wmanager=QtGui.QMdiArea()
self.setCentralWidget(self.wmanager)
# Shows the main window
self.showMaximized()
def open_window(self):
test_wdw.launch_window()
test_wdw.window_alpha=self.wmanager.addSubWindow(test_wdw.window)
# Shows the new window
test_wdw.window_alpha.show()
def main():
app=QtGui.QApplication(sys.argv)
main_wdw=Main_Window()
sys.exit(app.exec_())
if __name__=="__main__":
main()
这是测试的代码:
from PySide import QtGui
from PySide import QtCore
def launch_window():
global window
window=QtGui.QWidget()
window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
window.setWindowTitle('Window 1')
window.grid=QtGui.QGridLayout()
window.label=QtGui.QLabel("Hello")
window.grid.addWidget(window.label,0,0)
window.setLayout(window.grid)
window.setFixedSize(window.sizeHint())
class running_operation(QtCore.QObject):
# Function I would like to run in a separate thread
def run_operation(self):
while True:
print("hi")
myThread=QtCore.QThread()
operations = running_operation()
operations.moveToThread(myThread)
myThread.start()
我的问题是我不知道从这里走到哪里。我希望一旦启动新窗口,它就会在新线程中启动run\u operation()
函数
我试图添加操作。在test\u wdw
文件的末尾运行
,但实际情况是run\u operation()
在运行应用程序后立即开始执行,并且根本没有显示GUI
添加操作。在启动窗口函数中运行\u操作()
刚刚使GUI崩溃
这让我意识到,run\u操作
函数并没有像预期的那样在单独的线程中运行
我继续阅读文档,我相信我需要为它创建信号和插槽来运行。我知道如何使用信号和插槽将QObject
s连接到我希望它们在触发时执行的函数,但我不明白信号和插槽与QThread
有什么关系,我无法达到预期的结果
我想解释一下信号和插槽在QThread
上下文中的作用,以及它们是如何使用的,我想对我发布的代码进行更正,使其按预期运行
其他信息:
- 操作系统:Windows 7 64位
- Python版本:3.3
- PySide版本:1.2.1
<> UL>
在对C++教程进行了多次尝试和错误的解码之后,我最终找到了解决方案。
test_main
的代码保持不变
import sys
import test_wdw
from PySide import QtGui
from PySide import QtCore
class Main_Window(QtGui.QMainWindow):
def __init__(self):
super(Main_Window,self).__init__()
self.initUI()
def initUI(self):
self.statusBar()
self.new_window=QtGui.QAction("&Window alpha",self)
self.new_window.triggered.connect(self.open_window)
self.menu_bar=self.menuBar()
self.menu1=self.menu_bar.addMenu('&Menu 1')
self.menu1.addAction(self.new_window)
# Creates a QMdiArea to manage all windows
self.wmanager=QtGui.QMdiArea()
self.setCentralWidget(self.wmanager)
# Shows the main window
self.showMaximized()
def open_window(self):
test_wdw.launch_window()
test_wdw.window_alpha=self.wmanager.addSubWindow(test_wdw.window)
# Shows the new window
test_wdw.window_alpha.show()
def main():
app=QtGui.QApplication(sys.argv)
main_wdw=Main_Window()
sys.exit(app.exec_())
if __name__=="__main__":
main()
测试的正确代码为:
from PySide import QtGui
from PySide import QtCore
def launch_window():
global window
# Creates a new window
window=QtGui.QWidget()
window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
window.setWindowTitle('Window 1')
# Creates a layout for the window and populates it with a Qlabel
window.grid=QtGui.QGridLayout()
window.label=QtGui.QLabel("Hello")
window.grid.addWidget(window.label,0,0)
# Sets the layout to the window and sets the size of the window
window.setLayout(window.grid)
window.setFixedSize(window.sizeHint())
# Starts the thread
myThread.start()
class running_operation(QtCore.QObject):
# Creates a QtCore Signal for when the operation is over (if you want something to happen when the function ends processing)
finish_operation=QtCore.Signal()
# Wraps the function to run inside a QtCore Slot (MANDATORY !)
@QtCore.Slot()
# Function I wanted to run in a separate thread ! NOW IT RUNS !
def run_operation(self):
global counter
counter=0
# Setting a timer that fires every second and calling at the same time the function print_counter()
global timer
timer=QtCore.QTimer(self)
timer.timeout.connect(self.print_counter)
timer.start(1000)
def print_counter(self):
global counter
global timer
# A random function to execute just for testing purposes, the counter keeps counting up every second.
if counter <= 3 :
counter += 1
print(counter)
elif counter == 4 :
# At seconds, we emit the finish_operation signal.
counter += 1
self.finish_operation.emit()
# At 5 seconds and more, the counter keeps counting up again every second (just to check if the thread actually exited)
else:
counter += 1
print(counter)
# Creates a new thread
myThread=QtCore.QThread()
# Creates the object "operations"
operations = running_operation()
# Moves the object to the thread
operations.moveToThread(myThread)
# Connects the QThread.started signal function to the run_operation() function.
myThread.started.connect(operations.run_operation)
# Connects the finish_operation signal to quitting the thread.
operations.finish_operation.connect(myThread.quit)
从PySide导入QtGui
从PySide导入QtCore
def启动_窗口():
全局窗口
#创建一个新窗口
window=QtGui.QWidget()
setAttribute(QtCore.Qt.WA_DeleteOnClose)
window.setWindowTitle(“窗口1”)
#为窗口创建布局并使用Qlabel填充它
window.grid=QtGui.QGridLayout()
window.label=QtGui.QLabel(“你好”)
window.grid.addWidget(window.label,0,0)
#设置窗口的布局并设置窗口的大小
window.setLayout(window.grid)
window.setFixedSize(window.sizeHint())
#开始线程
myThread.start()
类运行_操作(QtCore.QObject):
#为操作结束时创建QtCore信号(如果您希望函数结束处理时发生某些事情)
完成\u操作=QtCore.Signal()
#包装要在QtCore插槽中运行的函数(必需!)
@QtCore.Slot()
#我想在一个单独的线程中运行的函数!现在它跑了!
def run_操作(自):
全局计数器
计数器=0
#设置每秒触发的计时器,同时调用函数print_counter()
全局计时器
定时器=QtCore.QTimer(自身)
定时器.超时.连接(自打印计数器)
定时器启动(1000)
def打印计数器(自身):
全局计数器
全局计时器
#一个仅用于测试目的的随机函数,计数器每秒都在计数。
如果计数器