2017-12-25 26 views
1

Arduino 보드에서 읽는 데 사용하는 Python 코드 (PyCharm)가 있습니다. 독서 자체는 괜찮습니다. 나는 코드의 Tkinter의 부분에 다음과 같은 두 가지 문제가있다 :tkinter에서 그래프를 계속 업데이트합니다.

코드가 나는 버튼이 시작 '( 을 클릭합니다 반면, 즉시이 가 시작됩니다으로 아두 이노에서 값을 읽을 시작
  1. read_data '); 'read_data'버튼을 누르지 않는 한, 그래프는 표시되지 않지만 판독 값이 취해집니다. 내가 볼 수있는 때 나는 코드를 실행하기 시작한 후 몇 초 동안 그래프를 연다.
  2. 플롯 close_plot을 닫으면 그래프 창이 실제로 닫히고 나중에 잠시 후에 다시 열립니다.

나는이 지속적으로 mainloop() 내에서 실행되고, 따라서 read_data 기능을 지속적으로 업데이트 될 때 문제가 Top.after에있다 생각합니다. 이 문제를 어떻게 해결할 수 있습니까?

import serial 
from tkinter import * 
from matplotlib import pyplot as plt 

Top = Tk() 

ser = serial.Serial('COM3', baudrate=9600, timeout=1) 

x = [] 
y = [] 

def read_data(): 
    plt.ion() 
    new_value = ser.readline().decode('ascii') 
    if new_value == '': 
     pass 
    else: 
     y.append(eval(new_value[:-2])) 
     x.append(len(y) - 1) 
     plt.plot(x, y, 'r-') 
     plt.show() 
     plt.pause(0.0001) 
     Top.after(100, read_data) 

def close_plot(): 
    plt.close() 
    global x, y 
    x = [] 
    y = [] 

def quit(): 
    Top.destroy() 

Button(Top, text='Read', command=read_data).pack() 
Button(Top, text='Close plot', command=close_plot).pack() 
Button(Top, text='Quit', command=quit).pack() 

Top.after(100, read_data) 
mainloop() 

편집 : read_data 버튼을 누를 때, 나는 다음과 같은 경고를 얻을 :

C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\backend_bases.py:2445: MatplotlibDeprecationWarning: Using default event loop until function specific to this GUI is implemented warnings.warn(str, mplDeprecation) 
+1

1. 'mainloop()'이전에'Top.after (100, read_data) '를 제거하십시오 - 프로그램 시작 후 100ms를 읽는 것을 시작합니다. – furas

+1

BTW : [PEP 8 - 스타일 가이드 (Python 코드)] (https://www.python.org/dev/peps/pep-0008/)를 읽어보십시오. 우리는 'Button','Tk' 또는'Serial'과 같은 클래스 이름에만 "대문자 이름"을 사용하지만'Top'과 같은 변수에는 사용하지 않습니다. 코드를 더 읽기 쉽게 만듭니다. 'Stackoverflow'조차도이 규칙을 알고 클래스에 하늘색을 사용합니다. – furas

+0

@furas : 귀하의 제안이 도움이되지 않을까 걱정됩니다. 코드가 실행되는 즉시 코드가 계속 읽기 시작합니다. – DenGor

답변

1

첫째, 라인 제거 : 즉시mainloop() 전에 furas를 같이 제공

Top.after(100, read_data) 

을 제안했다.

그런 read_data 매 100 밀리 호출 중지 after_cancel 방법을 추가 할 수 있지만 그 일을 위해, 우리는 우리가 먼저 글로벌 변수에 메소드 내에서 사용 after를 할당 할 필요가 : 마지막으로 전화 한 후

func_id = Top.after(100, read_data) 

after_cancelclose_plot에서 :

Top.after_cancel(func_id) 

코드는 정확히 아래와 같이해야합니다 :

import serial 
from tkinter import * 
from matplotlib import pyplot as plt 

Top = Tk() 

ser = serial.Serial('COM3', baudrate=9600, timeout=1) 

x = [] 
y = [] 
func_id = None 

def read_data(): 
    global func_id 
    plt.ion() 
    new_value = ser.readline().decode('ascii') 
    if new_value == '': 
     pass 
    else: 
     y.append(eval(new_value[:-2])) 
     x.append(len(y) - 1) 
     plt.plot(x, y, 'r-') 
     plt.show() 
     plt.pause(0.0001) 
    func_id = Top.after(100, read_data) 

def close_plot(): 
    global func_id 
    #to no longer update the plot 
    Top.after_cancel(func_id) 
    plt.close() 
    global x, y 
    del x[:] 
    del y[:] 

def quit(): 
    Top.destroy() 

Button(Top, text='Read', command=read_data).pack() 
Button(Top, text='Close plot', command=close_plot).pack() 
Button(Top, text='Quit', command=quit).pack() 

mainloop() 
+0

나는'after()'를'if/else'의 외부에 두어 모든 시간을 읽을 수 있도록 할 것이지만 그것을 테스트 할 수는 없습니다. – furas

+0

@furas 좋은 전화. 나는 그에 따라 고쳐 줄 것이다. 감사! – Nae

+1

BTW :'socat'을 사용하여 Linux에서 테스트하여 가짜 직렬 포트와 같은 대답을 만들려고합니다. https://stackoverflow.com/a/23255001/1832058 – furas