Tkinter没有在按键之间保存值?

时间:2015-12-04 01:51:23

标签: python python-2.7 tkinter

至少我认为那是怎么回事......

我通过串行连接运行两台电机。电机R的控制值范围为1 - 127,电机L的范围为128至255.

我正在使用tkinter来捕捉箭头键按下,然后我将其解释为馈送到电机,这工作正常,除了我想保存当前状态或电机所以我可以知道我是否需要更换电机下一个按键。

在添加多线程之前,它一直有效。

这是试图保存状态的代码:

def save_cur_state(save_state):
    print'save_state'
    print save_state
    print'okay'
    if (save_state > 0 and save_state < 128):
        last_goodR(save_state)
    elif (save_state < 256 and save_state > 127):
        last_goodL(save_state)
    else:
        print'wtf?'

def last_goodR(n):
    global cur_stateR_save
    cur_stateR_save = n
    print 'RRRRRR'
    print cur_stateR

def last_goodL(n):
    global cur_stateL_save
    cur_stateL_save = n
    print'LLLL'
    print cur_stateL

def get_cur_state():
    global cur_stateR_save
    global cur_stateL_save
    print 'accessing saves'
    print cur_stateR_save
    print cur_stateL_save

    cur_stateR = cur_stateR_save
    cur_stateL = cur_stateL_save
    return(cur_stateL, cur_stateR)

一切似乎都运行良好,我的版画都给了他们应该做的。 但是,当我再次按下该键时,“已保存”的值都默认为零,我不知道为什么。我已经尝试了十亿种不同的方法来解决它,但我无法让这些值得坚持下去。有谁知道为什么会出现这种情况或我应该如何解决它? (我的整个代码如下,如果你想看到它) 谢谢!!

import rospy
from std_msgs.msg import Int64
from Tkinter import *
import time
from serial import Serial
from multiprocessing import Process


#Defines
M1B = 1
M1S = 64
M1F = 127
M2B = 128
M2S = 192
M2F = 255

S = 0
F = 1
B = 2
L = 3
R = 4


#serialPort = Serial('/dev/ttyAMA0', 9600, timeout = 2)
cur_stateR = M1S
cur_stateL = M2S
next_stateR = M1S
next_state = M2S

main = Tk()


def kp(event):
    if event.keysym == 'Up' :
        direction_set(F)
    elif event.keysym =='Down' :
        direction_set(B)
    elif event.keysym =='Left' :
        direction_set(L)
    elif event.keysym =='Right' :
        direction_set(R)
    else :
        print'fooo'
        try:
            print'try'
            cur_stateR
            cur_stateL
        except NameError:
            print'except'

            cur_stateR = 0
            cur_stateL = 0
            last_goodR(0)
            last_goodL(0)


def direction_set(direction):
    if direction == F:
        next_stateR = M1F
        next_stateL = M2F
    elif direction == B:
        next_stateR = M1B
        next_stateL = M2B
    elif direction == R:
        next_stateR = M1B
        next_stateL = M2F
    elif direction == L:
        next_stateR = M1F
        next_stateL = M2B
    elif direction == S:
        next_stateR = M1S
        next_stateL = M2S
    else:
        next_stateR = M1S
        next_stateL = M2S
    update(next_stateR, next_stateL)

def update(next_stateR, next_stateL):
    if (cur_stateR != next_stateR):
        p1 = Process(target = motor1, args = (next_stateR,))
        p1.start()

    if (cur_stateL != next_stateL):
        p2 = Process(target = motor2, args = (next_stateL,))
        p2.start()


def motor1(next_stateR):
    #change the R motor
    print'start motor1'
    cur_stateR, cur_stateL = get_cur_state()
    if (cur_stateR != next_stateR):
        #first set to 64 
        cur_stateR = M1S
        refresh(cur_stateR)
        time.sleep(1)
        # then itterate to the desired stat
        if next_stateR == M1F:
            for x in range (M1S, M1F+1):
                cur_stateR = x
                time.sleep(.01)
                refresh(cur_stateR)
        elif next_stateR == M1B:
            for x in range (M1S, M1B-1, -1):
                cur_stateR = x
                time.sleep(.01)
                refresh(cur_stateR)

    save_cur_state(cur_stateR)
    print 'end motor1'

def motor2 (next_stateL):
    #change the L motor
    print 'start motor2'
    cur_stateR, cur_stateL = get_cur_state()
    if (cur_stateL != next_stateL):
        #first set to 64
        cur_stateL = M2S
        refresh(cur_stateL)
        time.sleep(1)
        # then itterate to the desired stat
        if next_stateL == M2F:
            for x in range (M2S, M2F+1):
                cur_stateL = x
                time.sleep(.01)
                refresh(cur_stateL)
        elif next_stateL == M2B:
            for x in range (M2S, M2B-1, -1):
                cur_stateL = x
                time.sleep(.01)
                refresh(cur_stateL)
    #print 'to save:'
    #print cur_stateR
    #print cur_stateL   
    save_cur_state(cur_stateL)

def refresh(update_state):
    #serialPort.write(chr(update_state))
    print update_state

def save_cur_state(save_state):
    print'save_state'
    print save_state
    print'okay'
    if (save_state > 0 and save_state < 128):
        last_goodR(save_state)
    elif (save_state < 256 and save_state > 127):
        last_goodL(save_state)
    else:
        print'wtf?'
''' try:
        print'try'
        cur_stateR
        cur_stateL
    except NameError:
        print'except'

        cur_stateR = 0
        cur_stateL = 0
        last_goodR(0)
        last_goodL(0)
    else:'''


def last_goodR(n):
    global cur_stateR_save
    cur_stateR_save = n
    print 'RRRRRR'
    print cur_stateR

def last_goodL(n):
    global cur_stateL_save
    cur_stateL_save = n
    print'LLLL'
    print cur_stateL

def get_cur_state():
    global cur_stateR_save
    global cur_stateL_save
    print 'saves acess'
    print cur_stateR_save
    print cur_stateL_save

    cur_stateR = cur_stateR_save
    cur_stateL = cur_stateL_save
    return(cur_stateL, cur_stateR)


main.bind_all('<KeyPress>', kp)


main.mainloop()

serialPort.close()

1 个答案:

答案 0 :(得分:0)

首先,在尝试使用&#34;线程&#34;做之前,您应该知道tkinter不是线程安全的;除了创建它们的线程之外,不应该从任何东西访问GUI元素,任何跨线程的使用最多都是不可靠的,并且在其余时间保证是错误的。

其次,您实际上并未参与线程化。您正在使用生成新进程的multiprocessing,并且这些进程不会与生成它们的进程共享内存(包括全局变量等内容),除非在非常有限的情况下(例如multiprocessing.Array )。在类UNIX系统上,他们使用fork,并且一旦Process开始运行,它就具有原始进程具有的写时复制视图;它可以从fork的那一刻开始读取相同的数据,但是如果它改变它,它只会更改自己的副本,而不是父进程的副本。 set_cur_state中的motor1调用是设置子进程的值副本,但原始进程的副本未经修改。

如果您想使用threading(使用线程,而不是进程)进行工作,则可以构建this simple example of how to do so

如果您正在使用multiprocessing,则可以使用multiprocessing.Queue采取类似的方法。或者,您可以使用全局multiprocessing.Pool,而不是启动新的Process,当您需要调度工作时,您可以在池上调用apply_async,将功能更改为接受状态作为参数并返回新状态(而不是在内部读取和写入全局变量),并向callback提供将使用返回值调用的apply_async函数。注意:据我所知,callback将使用与工作者通信的线程调用,而不是主线程,因此您仍需要使用示例代码中的技巧将数据传递回所拥有的小部件由主线。