2016-07-29 14 views
0

「の後に」私は(唯一のウィンドウ/ボタンを描き、その上の)私の作業Tkinterのコードを取り、ここで承認された解答からいくつかのコードを追加しようとしました:python code for serial data to print on window.は「桂」オブジェクトが属性を持っていない

承認答えを非常に小さな変更を加えたものの、私のコードに追加されました。エラーが発生しました。 "'Gui'オブジェクトには 'after'属性がありません。"

"after"属性が検索される理由はわかりません。 process_serialの代わりにGuiクラスを使用します。

from tkinter import * 
from tkinter import ttk 

import serial 
import threading 
import queue 

class SerialThread(threading.Thread): 
    def __init__(self, queue): 
     threading.Thread.__init__(self) 
     self.queue = queue 
    def run(self): 
     s = serial.Serial('COM11',115200) 
     while True: 
      if s.inWaiting(): 
       text = s.readline(s.inWaiting()) 
       self.queue.put(text) 

class Gui(): 
    def __init__(self, master): 
     ###MAIN FRAME### 
     mainFrame = Frame(master, width=50000, height=40000) 
     mainFrame.pack(fill = BOTH, expand = 1) 

     ###LIST FRAME### 
     listFrame = Frame(mainFrame) 
     listFrame.pack(side = TOP, fill = BOTH, expand = 1) 

     self.sensorList = ttk.Treeview(listFrame) 

     self.sensorList["columns"]=("MAC","Type","Value","Voltage","Firmware","Rate","RSSI") 
     self.sensorList.column("MAC", width=200, minwidth=200) 
     self.sensorList.column("Type", width=100, minwidth=100) 
     self.sensorList.column("Value", width=100, minwidth=100) 
     self.sensorList.column("Voltage", width=100, minwidth=100) 
     self.sensorList.column("Firmware", width=100, minwidth=100) 
     self.sensorList.column("Rate", width=100, minwidth=100) 
     self.sensorList.column("RSSI", width=100, minwidth=100) 
     self.sensorList.heading("MAC", text="MAC") 
     self.sensorList.heading("Type", text="Type") 
     self.sensorList.heading("Value", text="Value") 
     self.sensorList.heading("Voltage", text="Voltage") 
     self.sensorList.heading("Firmware", text="Firmware") 
     self.sensorList.heading("Rate", text="Rate") 
     self.sensorList.heading("RSSI", text="RSSI") 

     self.sensorList.pack(fill = BOTH, expand = 1, pady=5, padx=5) 

     ###TEXT AREA FRAME### 
     textAreaFrame = Frame(mainFrame) 
     textAreaFrame.pack(side = TOP, fill = BOTH, expand = 1) 

     self.textArea = Text(textAreaFrame) 
     self.textArea.pack(fill = BOTH, expand = 1, pady=5, padx=5) 

     ###INPUT FRAME### 
     inputFrame = Frame(mainFrame) 
     inputFrame.pack(side = BOTTOM, fill = X, expand = 0) 

     self.input = Entry(inputFrame) 
     self.input.pack(side=LEFT, fill = X, expand = 1, pady=5, padx=5) 

     self.comboAction = ttk.Combobox(inputFrame) 
     self.comboAction.pack(side = LEFT, pady=5, padx=5) 

     self.comboDevice = ttk.Combobox(inputFrame) 
     self.comboDevice.pack(side = LEFT, pady=5, padx=5) 

     self.sendButton = Button(
      inputFrame, text="SEND", command=mainFrame.quit 
     ) 

     self.sendButton.pack(side=LEFT,pady=5, padx=5) 

     #self.button = Button(
     # mainFrame, text="QUIT", fg="red", command=mainFrame.quit 
     #) 
     #self.button.pack(side=LEFT) 

     #self.hi_there = Button(mainFrame, text="Hello", command=self.say_hi) 
     #self.hi_there.pack(side=LEFT) 

     ###AFFIX MINIMUM SIZE OF MAIN WINDOW TO PREVENT POOR SIZING### 
     master.update() 
     master.minsize(root.winfo_width(), root.winfo_height()) 
     master.minsize(master.winfo_width(), master.winfo_height()) 

     ###SERIAL PORT### 
     self.queue = queue.Queue() 
     thread = SerialThread(self.queue) 
     thread.start() 
     self.process_serial() 

    def process_serial(self): 
     while self.queue.qsize(): 
      try: 
       self.textArea.delete(1.0, 'end') 
       self.textArea.insert('end', self.queue.get()) 
      except Queue.Empty: 
       pass 
     self.after(100, self.process_serial) 



    def say_hi(self): 
     s = self.input.get() 
     print ("hi there, everyone!" + s) 

root = Tk() 

gui = Gui(root) 

root.mainloop() 
root.destroy() # optional; see description below 

答えて

4

のサブクラスを作成する必要があり'after'関数を持つtkinterオブジェクトではありません。

リンクされた質問のコードとコードの間に不一致があります。あなたのクラスはtkinterオブジェクトを拡張しません。答えにおけるクラスはTkinterのTkのオブジェクトので、同じように拡張:

class App(tk.Tk): 

。これによりTkのクラスから機能を継承します。

これをコードで解決するには、process_serial関数のselfを、self.textAreaのようなtkinterオブジェクトに置き換えます。

self.textArea.after(100, self.process_serial) 

また、リンクされた回答のようにtk.Tkをサブクラス化することもできます。しかし、私はここに付加的な利益を見ません。

+0

ありがとうございます。これはうまくいったが、何が起こったかを本当に理解するのに時間を費やさなければならない。 これが解決された後、私のプログラムは正常に終了していません。私はcmd行入力に戻ってこないことを意味し、Ctrl + Cを押しても何も起こりません。私は最後のroot.destroy()を削除しました。なぜなら、それはすでに破壊されているというエラーを投げたからです。 私はそのprocess_serialループを実行していますか? – HSPalm

+1

アプリケーションの閉じるボタンはデフォルトで破棄されます。その後、root.mainloop()関数から出て、root.destroy()を呼び出そうとします。これはすでに破壊されているため失敗します。したがって、root.destroy()は不要です。 mainloop()が動いているので、あなたはcmd行に戻ってくるべきではありません。 ctrl-Cを押してアプリケーションを終了させるには、スレッドのthread.daemonをTrueに設定します。 – Munchhausen

+0

参照:https://docs.python.org/3/library/threading.html#threading.Thread.daemon参照:http://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.mainloop-method – Munchhausen

1

Tkinter.Tkから継承されたafter方法。ここにある

self.after(100, self.process_serial) 

自己変数は、GUIオブジェクトを参照し、:Check mentioned question

おそらく犯人はprocess_serial機能で、このラインであるTkinter.Tk

... 
import Tkinter 
class Gui(Tkinter.Tk) 
    ... 
関連する問題