### 把matplotlib包裝成獨立視窗 ```python class Plot2D(Frame): def __init__(self, parent, dataCollector, **kwargs): Frame.__init__(self, parent.mainWindow, **kwargs) self.parent = parent self.mainWindows = Toplevel(parent.mainWindow) self.mainWindows.title("AF State") self.figure = plt.Figure(figsize=(9,5), dpi=100) self.figure.suptitle('AF value plot', fontsize=16) self.ax = self.figure.add_subplot(111) self.canvas = FigureCanvasTkAgg(self.figure, master=self.mainWindows) self.canvas.get_tk_widget().pack(fill='both') self.axline = None self.dataCollector = dataCollector self.dataCollector.start() def close(self): print("Plot2D close") self.mainWindows.destroy() self.dataCollector.stop() self.dataCollector = None def draw(self): if self.dataCollector: datax, datay = self.dataCollector.getPlotData() self.ax.clear() self.ax.set_xlabel('Last {} datas'.format(self.dataCollector.getDataLength())) self.axline, = self.ax.plot(datax, datay) self.canvas.draw() def getWindow(self): return self.mainWindows def getLastData(self): return self.dataCollector.getLastData() ``` 其中這一行: ```python self.mainWindows = Toplevel(parent.mainWindow) ``` 是用來開一個新的視窗,其中的`parent.mainWindow`就是用`tk.TK()`所產生出來的root。 因為需要一直更新資料,所以需要的一個`DataCollector`來提供資料,`DataCollector`會提供畫圖需要的list,如: ```python datax, datay = self.dataCollector.getPlotData() ``` `DataCollector`的定義如下: ```python class AfStateCollector(threading.Thread): def __init__(self, dataLength=100, pollingInterval=0.033): threading.Thread.__init__(self) self.dataLength = dataLength self.pollingInterval = pollingInterval self.stopEvent = threading.Event() self.data = [] self.xdata = [] def run(self): while True: if self.stopEvent.is_set(): break afValue = self.readAf() self.data.append(afValue) self.xdata.append(len(self.xdata)) if len(self.data) > self.dataLength: self.data = self.data[-self.dataLength:] self.xdata = list(range(self.dataLength)) # print(f'afValue = {afValue}') time.sleep(self.pollingInterval) print("AfStateCollector stopped.") def readAf(self): ReadTestXUreg_cmd = "lvreg testxu read 10" ReadTestXUreg_cmd_process = subprocess.Popen(ReadTestXUreg_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) outstring, err = ReadTestXUreg_cmd_process.communicate() outstring = outstring.strip().decode('utf-8') outstring = int(outstring, 16) outstring_H = (outstring & 0xFF00) / 256 outstring_L = outstring & 0xFF outAFStat = int(outstring_L * 256 + outstring_H) return outAFStat ``` - [Python GUI之tkinter視窗視窗教程大集合(看這篇就夠了) - IT閱讀](https://www.itread01.com/content/1547705544.html) - [【Python】改善 VideoCapture 的影像延遲 | 夏恩的程式筆記 - 點部落](https://dotblogs.com.tw/shaynling/2017/12/28/091936) - [Displaying a video feed with OpenCV and Tkinter - PyImageSearch](https://www.pyimagesearch.com/2016/05/30/displaying-a-video-feed-with-opencv-and-tkinter/)