2016-01-23 89 views
0

我已经绑定了一个函数调用Kivy按钮,它构建并启动两个线程。我正在使用Kivy标签来显示我确实正在输入函数'my_function()'并结束。看来这些线程没有正确构建。Python函数在函数调用时没有正确执行(Kivy)

这两个线程的每一个都旨在转动步进电机。我测试了这些电机并且它们工作正常,但是当我尝试将代码放入一个函数并在变量上应用'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代码()和施加 '自我';线程不再工作。为第二个线程重复代码。我想强调的是,这个代码工作时内部没有一个功能,而不是用“自我”:

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

您正在将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) 

我希望这将有助于。也看看你是否真的需要定义自选画面下,这些方法...

还要注意的是,如果线程要访问kivy UI他们需要通过调用时钟做到这一点(所以你必须线程安全)

+0

在stepper_worker中添加自我作为第一个参数固定它!谢谢。 – Finksterr