2016-01-23 119 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