Jako tytuł mam problem, aby użyć funkcji, która zawiera funkcję pętli kilka razy. Reulst jest tym, czego chcę. Próbowałem go rozwiązać na przykład przez listę, funs_list = [miara ("A"), zmierz ("B")], ale taki sam wynik. Funkcja pętli nie uruchomi się krok po kroku za każdym razem.

from Tkinter import *
import time

def measure(name):
    global voltage, data

    data = []
    if name == "A":
        voltage = -0.2
        limits = +0.2
    else:
        voltage = -0.1
        limits = +0.1
    def loop():
            global voltage , data
            data.append(round(voltage,3))

            voltage += 0.02

            if voltage > -0.01:
                voltage = 0
                data.append(round(voltage,3))
                root.after_cancel(loop)
                print 'data', data

            else:
                root.after(1000, loop)
    root.after(1, loop)



def others():
    global data

    measure("A")
    A = data
    print 'A', A


    measure("B")
    B = data
    print 'B', B

    print 'i am here'



root = Tk()
root.title("A Tool")
Button(root, text="Test other",width=38, height = 8, bg='gray',command=lambda:others()).pack()

root.mainloop()

Po naciśnięciu przycisku "inne, wynik jest jak:

    A []
    B []
    i am here
    data [-0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    data [-0.1, -0.08, -0.06, -0.04, -0.02, 0.0, 0.0, 0.0]

Ale chcę mieć jak np. Poniżej, który wykonuje krok po kroku funkcji. Co powinienem zrobić ?

    data [-0.2, -0.18, -0.16, -0.14, -0.12, -0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    A [-0.2, -0.18, -0.16, -0.14, -0.12, -0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    data [-0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    B [-0.1, -0.08, -0.06, -0.04, -0.02, 0.0]
    i am here
0
Morgan Song 18 październik 2017, 13:09

2 odpowiedzi

Najlepsza odpowiedź

Jeśli rozumiem problem prawidłowo, wygląda na to, że nie chcesz measure, aby powrócić do momentu uruchomienia pętli. Jeśli tak jest, możesz użyć zdolności TKinter, aby czekać na ustawienie zmiennej przed kontynuowaniem.

Możesz spróbować modyfikować swój kod, aby wyglądał następująco:

def measure(name):
    flag = BooleanVar()
    ...
    def loop():
        ...
        if voltage > -0.01:
            ...
            print 'data', data
            flag.set(True)
        ...
    loop()
    root.wait_variable(1000, loop)

Z powyższym, measure nie powróci, dopóki flaga zostanie ustawiona, a flaga nie zostanie ustawiona, dopóki nie zostanie zakończona.

Rozwiązanie oparte na zdarzeniu

Osobiście jednak nigdy tego nie zrobiłbym. Wydaje się, że to, co próbujesz zrobić, to powiedzieć "Zrób coś, gdy napięcie wzrośnie powyżej progu". Wschodzące napięcie może być uważane za jedynie inne zdarzenie, tak jak kliknięcie przycisku lub wpisując tekst.

Jeśli tak jest, możesz utworzyć i wiązać się z zdarzenia wirtualne .

Na przykład możesz utworzyć zdarzenia "<<Voltage-A>>" i "<<Voltage-B>>", które reprezentują napięcia A i B rosnące. Możesz wiązać się z tymi wydarzeniami, aby kiedy się zdarzają, robisz wszystko, co musisz zrobić. Ponadto, ponieważ chcesz zmierzyć B tylko po wzroście napięcia, możesz wywołać pomiar b na tym samym zdarzeniu.

Oto nieco wymyślony przykład na podstawie oryginalnego kodu:

from Tkinter import *

def measure(name):
    global voltage, data

    data = []

    if name == "A":
        voltage = -0.2
        limits = +0.2
    else:
        voltage = -0.1
        limits = +0.1
    def loop():
            global voltage , data
            data.append(round(voltage,3))

            voltage += 0.02

            if voltage > -0.01:
                voltage = 0
                data.append(round(voltage,3))
                root.after_cancel(loop)
                event_name = "<<Voltage-%s>>" % name
                print 'data', data
                root.event_generate(event_name)

            else:
                root.after(1000, loop)

    loop()

def print_data(name):
    global data
    print name, data

root = Tk()
root.title("A Tool")
Button(root, text="Test other",width=38, height = 8, bg='gray',command=lambda:measure("A")).pack()

root.bind("<<Voltage-A>>", lambda event: (print_data("A"), measure('B')))
root.bind("<<Voltage-B>>", lambda event: print_data("B"))

root.mainloop()
0
Bryan Oakley 18 październik 2017, 16:36

Nie ma eksperta w Tkinter Ale problem tutaj jest złe użycie root.after().

Twoja funkcja measure() już zwróciła i wydrukowała, ale dlatego, że root.after() nadal nie został jeszcze wezwany, ponieważ musi czekać kilka ms, otrzymujesz pusty stół. Potem po tych karach MS dane są aktualizowane, ale wszystko, czego można się spodziewać, jest już zakończone.

Nieco zmieniłem kod:

def measure(name):
    ...
    def loop():
            ...

            if voltage > -0.01:
                voltage = 0
                data.append(round(voltage,3))

                print ('data', data)
                return  # root.after_cancel(loop)

            else:
                loop()  # root.after(1, loop)

    loop()  # root.after(1, loop)

A oto mój wynik:

data [-0.2, -0.18, -0.16, -0.14, -0.12, -0.1, -0.08, -0.06, -0.04, -0.02, 0] A [-0.2, -0.18, -0.16, -0.14, -0.12, -0.1, -0.08, -0.06, -0.04, -0.02, 0]

0
Łukasz Szczesiak 18 październik 2017, 11:01