qpython3h怎么用_Python上Qt中的QThread

在阅读了有关应如何使用QThread的扩展讨论并通过子类覆盖它的run方法之后,我使用了一个Worker对象来使用QThread,这是不合适的方法.但是,在我打算使用的方法中,我需要传递一个附加的函数参数,该参数在线程启动以及使用moveToThread将工作程序推入线程时不可用.该信息(参数)在按下按钮时可用,并传达有关要移动的对象的信息.

在我的代码的完整版中,有3个单独的控制器,用于3个单独的对象,您可以在下面找到一个最小的工作示例,以说明我尝试传递参数的内容.该代码也可以在pastebin上使用,并且感兴趣的行号是10-28、46-50和133-135.

到目前为止,我已经尝试在连接到worker中实际函数的行中使用lambda构造函数.那行是self.thread.started.connect(self.obj.moveLeftIncrement)然后尝试使用插槽,但是我不太了解它们.此外,尽管使用了QThread,但有时GUI仍挂起,并且在程序退出后仍会出现错误,其中之一如下:

Process finished with exit code -1073740791 (0xC0000409)

我的问题如下:

>如何在运行时传递参数和/或使用插槽?

>如何防止退出时出现程序错误?

>为什么不推荐使用子类化QThread在这种情况下直接起作用?

from PySide2.QtCore import *

from PySide2.QtWidgets import *

from PySide2.QtGui import *

import sys

import time

class Worker(QObject):

finished = Signal(int)

@Slot(str)

def moveLeftIncrement(self, controller_name):

# controller_name = "Controller 1"

print("Controller name is ", controller_name)

if controller_name == "Controller 1":

print("Starting controller 1")

time.sleep(2)

print("Finishing sleep")

elif controller_name == "Controller 2":

print("Starting controller 2")

time.sleep(2)

print("Finishing sleep")

elif controller_name == "Controller 3":

print("Starting controller 3")

time.sleep(2)

print("Finishing sleep")

else:

raise Exception("No such controller found!")

self.finished.emit(0)

class Window(QWidget):

""" Inherits from QWidget """

def closeEvent(self, *args, **kwargs):

print("\nClosing")

def __init__(self):

super().__init__()

self.CONTINUOUS_MOVE_SWITCH = False

self.title = 'Control Controllers'

self.left = 10

self.top = 10

self.width = 320

self.height = 100

self.AxesMapping = [0, 1, 2, 3]

self.initUI()

self.thread = QThread()

self.obj = Worker()

self.obj.moveToThread(self.thread)

self.thread.started.connect(self.obj.moveLeftIncrement)

self.obj.finished.connect(self.thread.quit)

def initUI(self):

""" Initializes the GUI either using the grid layout or the absolute position layout"""

self.setWindowTitle(self.title)

self.setGeometry(self.left, self.top, self.width, self.height)

Comp1 = self.createGridLayout("Controller 2")

windowLayout = QGridLayout()

windowLayout.addWidget(Comp1, 0, 0)

self.setLayout(windowLayout)

self.show()

def createGridLayout(self, controller):

"""Creates a grid layout for the buttons"""

box_size = QSize(640, 440)

HGroupBox = QGroupBox(controller)

layout = QGridLayout()

layout.addWidget(self.createButton("left", controller), 2, 1)

layout.addWidget(self.createButton("right", controller), 2, 3)

layout.addWidget(self.createButton("forward", controller), 1, 2)

layout.addWidget(self.createButton("backward", controller), 3, 2)

HGroupBox.setLayout(layout)

HGroupBox.setFixedSize(box_size)

return HGroupBox

def createButton(self, name, controller):

"""Creates a button with the specified size"""

button_size = QSize(100, 40)

icon_size = 40

button = QPushButton()

button.Name = name

button.Controller = controller

button.Moving = 0

button.clicked.connect(lambda: self.buttonPresssed(button))

button.setFixedSize(button_size)

return button

def moveLeftIncrement(self, controller, button):

if controller == "Controller 1":

time.sleep(2)

elif controller == "Controller 2":

time.sleep(2)

elif controller == "Controller 3":

time.sleep(2)

else:

raise Exception("No such controller found!")

def moveRightIncrement(self, controller, button):

if controller == "Controller 1":

time.sleep(2)

elif controller == "Controller 2":

time.sleep(2)

elif controller == "Controller 3":

time.sleep(2)

else:

raise Exception("No such controller found!")

def moveForwardIncrement(self, controller, button):

if controller == "Controller 1":

time.sleep(2)

elif controller == "Controller 2":

time.sleep(2)

elif controller == "Controller 3":

time.sleep(2)

else:

raise Exception("No such controller found!")

def moveBackwardIncrement(self, controller, button):

if controller == "Controller 1":

time.sleep(2)

elif controller == "Controller 2":

time.sleep(2)

elif controller == "Controller 3":

time.sleep(2)

else:

raise Exception("No such controller found!")

def buttonPresssed(self, button):

name = button.Name

if hasattr(button, 'Controller'):

controller = button.Controller

print("The controller selected is", controller)

if name == 'left':

self.thread.start()

elif name == 'right':

print("Moved controller right for a single step")

self.moveRightIncrement(controller, button)

elif name == 'forward':

self.moveForwardIncrement(controller, button)

print("Moved controller forward for a single step")

elif name == 'backward':

self.moveBackwardIncrement(controller, button)

print("Moved controller backward for a single step")

elif name == "up":

print("Moving controller up for a single step")

self.moveUpIncrement(controller, button)

elif name == "down":

print("Moving controller down for a single step")

self.moveDownIncrement(controller, button)

if __name__ == '__main__':

app = QApplication(sys.argv)

ex = Window()

sys.exit(app.exec_())

解决方法:

-如何在运行时传递参数和/或使用插槽?

如果要调用另一个线程中的对象的插槽,则必须使用信号,因为它是线程安全的.

-如何防止退出时出现程序错误?

在您的情况下,该错误是由于您正在运行一个线程而尚未停止它而引起的,一个可能的选择是使用closeEvent来停止它.

-为什么不推荐使用子类化QThread在这种情况下直接起作用?

并非不建议这样做,它是非常有限的,还有更好的选择,例如使用驻留在另一个线程中的工作程序,因此我们可以有不同的方法,而不仅仅是在run方法中执行任务.同样,通过worker的选择,您可以将多个对象置于一个线程中.

对于工人,方法如下:

>创建一个QThread并启动要处理的线程.

>创建一个将驻留在另一个线程中并移动另一个线程的对象

>连接调用对象插槽的信号,并连接将对象信息发送到GUI的信号.

>必要时发出它们将调用的信号.

考虑到上述情况,解决方案是:

from PySide2 import QtCore, QtGui, QtWidgets

import time

class Worker(QtCore.QObject):

error = QtCore.Signal()

@QtCore.Slot(str)

def moveLeftIncrement(self, controller):

if controller == "Controller 1":

time.sleep(2)

elif controller == "Controller 2":

time.sleep(2)

elif controller == "Controller 3":

time.sleep(2)

else:

self.error.emit("No such controller found!")

@QtCore.Slot(str)

def moveRightIncrement(self, controller):

if controller == "Controller 1":

time.sleep(2)

elif controller == "Controller 2":

time.sleep(2)

elif controller == "Controller 3":

time.sleep(2)

else:

self.error.emit("No such controller found!")

@QtCore.Slot(str)

def moveForwardIncrement(self, controller, button):

if controller == "Controller 1":

time.sleep(2)

elif controller == "Controller 2":

time.sleep(2)

elif controller == "Controller 3":

time.sleep(2)

else:

self.error.emit("No such controller found!")

@QtCore.Slot(str)

def moveBackwardIncrement(self, controller, button):

if controller == "Controller 1":

time.sleep(2)

elif controller == "Controller 2":

time.sleep(2)

elif controller == "Controller 3":

time.sleep(2)

else:

self.error.emit("No such controller found!")

class Window(QtWidgets.QWidget):

leftClicked = QtCore.Signal(str)

rightClicked = QtCore.Signal(str)

forwardClicked = QtCore.Signal(str)

backwardClicked = QtCore.Signal(str)

def __init__(self):

super().__init__()

self.CONTINUOUS_MOVE_SWITCH = False

self.title = 'Control Controllers'

self.left, self.top, self.width, self.height = 10, 10, 320, 100

self.AxesMapping = [0, 1, 2, 3]

self.initUI()

self.thread = QtCore.QThread(self)

self.thread.start()

self.obj = Worker()

self.obj.moveToThread(self.thread)

self.leftClicked.connect(self.obj.moveLeftIncrement)

self.rightClicked.connect(self.obj.moveRightIncrement)

self.forwardClicked.connect(self.obj.moveForwardIncrement)

self.backwardClicked.connect(self.obj.moveBackwardIncrement)

self.obj.error.connect(self.on_error)

def initUI(self):

self.setWindowTitle(self.title)

self.setGeometry(self.left, self.top, self.width, self.height)

Comp1 = self.createGridLayout("Controller 2")

windowLayout = QtWidgets.QGridLayout(self)

windowLayout.addWidget(Comp1, 0, 0)

def createGridLayout(self, controller):

"""Creates a grid layout for the buttons"""

box_size = QtCore.QSize(640, 440)

HGroupBox = QtWidgets.QGroupBox(controller)

layout = QtWidgets.QGridLayout()

layout.addWidget(self.createButton("left", controller), 2, 1)

layout.addWidget(self.createButton("right", controller), 2, 3)

layout.addWidget(self.createButton("forward", controller), 1, 2)

layout.addWidget(self.createButton("backward", controller), 3, 2)

HGroupBox.setLayout(layout)

HGroupBox.setFixedSize(box_size)

return HGroupBox

def createButton(self, name, controller):

button_size = QtCore.QSize(100, 40)

icon_size = 40

button = QtWidgets.QPushButton()

button.Name = name

button.Controller = controller

button.Moving = 0

button.clicked.connect(self.buttonPresssed)

button.setFixedSize(button_size)

return button

@QtCore.Slot()

def buttonPresssed(self):

button = self.sender()

name = button.Name

if hasattr(button, 'Controller'):

controller = button.Controller

print("The controller selected is", controller)

if name == 'left':

self.leftClicked.emit(controller)

elif name == 'right':

print("Moved controller right for a single step")

self.rightClicked.emit(controller)

elif name == 'forward':

print("Moved controller forward for a single step")

self.forwardClicked.emit(controller)

elif name == 'backward':

print("Moved controller backward for a single step")

self.backwardClicked.emit(controller)

@QtCore.Slot(str)

def on_error(self, error):

print(error)

def closeEvent(self, event):

self.thread.quit()

self.thread.wait()

super(Window, self).closeEvent(event)

if __name__ == '__main__':

import sys

app = QtWidgets.QApplication(sys.argv)

ex = Window()

ex.show()

sys.exit(app.exec_())

标签:multithreading,python-3-x,qthread,pyside2,python

来源: https://codeday.me/bug/20191211/2106669.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值