我已经对一个Kivy按钮进行了函数调用,该按钮构建并启动两个线程。我正在使用Kivy标签来表明我确实正在进入函数'my_function()'并一直走到最后。似乎线程没有正确构建。
两个螺纹各自旨在转动步进电机。我已经测试了这些电机并且它们可以正常工作,但是当我尝试将代码放在一个函数中并对变量应用'self'时,按钮按下没有任何反应,除了最后的标签被更新。
的Python:
import kivy
kivy.require('1.9.1')
from kivy.app import App
from kivy.uix.screenmanager import Screenmanager, Screen
from kivy.properties import StringProperty
from Adafruit_MotorHAT import Adafruit_MotorHAT, Adafruit_DCMotor, Adafruit_StepperMotor
import threading
import random
import time
import atexit
class ScreenManager(ScreenManager):
pass
class StartMenu(Screen):
pass
这是经过验证的真实代码:
class MyScreen(Screen):
entered = StringProperty("Not Entered")
# create a default object, no changes to I2C address or frequency
mh = Adafruit_MotorHAT()
# create empty threads (these will hold the stepper 1 and 2 threads)
st1 = Threading.thread()
st2 = Threading.thread()
# recommended for auto-disabling motors on shutdown!
def turnOffMotors(mh):
mh.getMotor(1).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(2).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(3).run(Adafruit_MotorHAT.RELEASE)
mh.getMotor(4).run(Adafruit_MotorHAT.RELEASE)
atexit.register(turnOffMotors(mh))
myStepper1 = mh.getStepper(200, 1) # 200 steps/rev, motor port #1
myStepper2 = mh.getStepper(200, 2) # 200 steps/rev, motor port #1
myStepper1.setSpeed(60) # 30 RPM
myStepper2.setSpeed(60) # 30 RPM
stepstyles = [Adafruit_MotorHAT.SINGLE, Adafruit_MotorHAT.DOUBLE, Adafruit_MotorHAT.INTERLEAVE, Adafruit_MotorHAT.MICROSTEP]
def stepper_worker(stepper, numsteps, direction, style):
stepper.step(numsteps, direction, style)
将代码放入my_function()并应用'self';线程不再有效。重复第二个线程的代码。我想强调一下,当代码不在函数内部而不使用'self'时,此代码可以工作:
def my_function(self, *args):
if (True):
time.sleep(0.005)
if not self.st1.isAlive():
randomdir = random.randint(0, 1)
if (randomdir == 0):
dir = Adafruit_MotorHAT.FORWARD
else:
dir = Adafruit_MotorHAT.BACKWARD
randomsteps = random.randint(10,50)
self.st1 = threading.Thread(target=self.stepper_worker, args=(self.myStepper1, randomsteps, dir, self.stepstyles[random.randint(0,3)],))
self.st1.start()
self.entered = "Entered"
构建
class MyApp(App):
def build(self):
return ScreenManager()
if __name__ == "__main__":
MyApp().run()
Kivy:my.kv
我遗漏了一些不必要的细节,例如布局和小部件大小。
#:kivy 1.9.1
<ScreenManager>:
StartMenu:
MyScreen:
<StartMenu>:
name: 'StartMenu'
Button:
on_release:
root.manager.current = 'MyScreen'
<MyScreen>:
name: 'MyScreen'
Label:
text: root.entered
Button:
on_release:
root.my_function()
谢谢你的时间!
答案 0 :(得分:0)
您将stepper_worker定义为MyScreen下的方法,因此它将获得的第一个参数是MyScreen的实例。
在您的示例中,您应该将其定义为函数或首先添加self参数。我假设您的线程无法启动,因为您发送了太多参数
# len(args) == 4 so you have too many parameters (the first is fixed to "self")
self.st1 = threading.Thread(target=self.stepper_worker, args=(self.myStepper1, randomsteps, dir, self.stepstyles[random.randint(0,3)],))
可能的解决方法如上所述:
#added self...
def stepper_worker(self, stepper, numsteps, direction, style):
stepper.step(numsteps, direction, style)
我希望这会有所帮助。还看看你是否真的需要在MyScreen下定义这些方法......
另请注意,如果线程想要访问kivy UI,则需要通过调用Clock来实现(因此您将拥有线程安全性)