2017-05-18 13 views
3

我正在嘗試使用Tkinter來可視化一些時間序列數據。我的數據是以二維矩陣的形式出現的,其中行指的是指代特定時間段的塊和列。所有的值都在0和1之間。如何使用Tkinter來顯示時間序列數據?

我想創建一個使用Tkinter的python腳本,它創建一個窗口,在方塊矩陣中顯示塊,第一列確定每個塊的亮度,然後在預定義時間量,根據數據中的連續列來更改塊的亮度。

我創造什麼,我至今一個簡化版本:

#!/usr/bin/python 

import sys 
import os.path 
import Tkinter as tk 
import math 

# program constants 
WINDOW_WIDTH = 900 

# function to change the colours of the blocks based on current period 
def redrawPeriod(t): 
    for b in xrange(len(blocks)): 
     luminance = int(blocks[b][t] * 255) 
     colour = "#%x%x%x" % (luminance,luminance,luminance) 
     canvas.itemconfig(block_ids[b],fill=colour) 

# sample data (4 blocks 4 periods) 
blocks = [ 
     [0.0, 0.2, 0.5, 0.8], 
     [0.3, 0.0, 0.4, 0.0], 
     [0.5, 0.7, 0.0, 1.0], 
     [0.0, 0.0, 0.3, 0.6], 
     [1.0, 0.5, 0.2, 0.9] 
     ] 

# get number of blocks and periods 
nB = len(blocks) 
nT = len(blocks[0]) 

n_cols = int(math.sqrt(nB)) 
n_rows = n_cols 

# if not perfect square number of blocks, add extra row 
if (nB % n_rows != 0): 
    n_rows = n_rows + 1 

# calculate block size 
BLOCK_SIZE = WINDOW_WIDTH/n_cols 
WINDOW_HEIGHT = BLOCK_SIZE * n_rows 

# initialise Tkinter 
root = tk.Tk() 

# initialise canvas 
canvas = tk.Canvas(root, width=WINDOW_WIDTH, height=WINDOW_HEIGHT, background="#002080") 

# open canvas 
canvas.pack() 

# container for block objects 
block_ids = [] 

x = 0 
y = -1*BLOCK_SIZE 

# initialise block objects 
for b in xrange(nB): 
    if (b % n_cols == 0): 
     x = 0 
     y = y + BLOCK_SIZE 

    luminance = int(blocks[b][0] * 255) 
    colour = "#%x%x%x" % (luminance,luminance,luminance) 
    id = canvas.create_rectangle(x, y, x+BLOCK_SIZE, y+BLOCK_SIZE, outline="",fill = colour) 
    block_ids.append(id) 
    x = x + BLOCK_SIZE 

for t in xrange(nT): 
    root.after(1000, redrawPeriod,t) 

root.mainloop() 

這似乎做什麼,我也想,但它直接跳到最後一幀每一次 - 即。它不繪製一幀,暫停,畫另一幀,再次暫停,等等。

任何人都可以請幫我找出我做錯了什麼嗎?

回答

1

你的問題是,當你撥打:

for t in xrange(nT): 
    root.after(1000, redrawPeriod,t) 

root.after()不會阻止執行,所以for循環執行速度非常快,那麼你所有重繪事件後1000毫秒同時調用。

在Tkinter中運行動畫的常用方法是編寫一個在延遲後自行調用的動畫方法(有關更多信息,請參閱Method for having animated movement for canvas objects pythonTkinter, executing functions over time)。

在你的情況,你可以做這樣的事情:

# Create all widgets 
... 

# Store the period indices to be redrawn ([0, 1, 2, ..., nT-1]) 
periods = range(nT) 

# Define the animation method 
def animation_loop(delay): 
    # Check if there are still periods to be drawn 
    if len(periods) > 0: 
     t = periods[0] 
     redrawPeriod(t) 
     # Remove the period that was just drawn from the list of periods 
     del periods[0] 
     # Call the animation_loop again after a delay 
     root.after(delay, animation_loop, delay) 

# Start the animation loop 
animation_loop(1000) 

# Launch the app 
root.mainloop() 
+1

謝謝,非常完美。我曾假定'root.after()'調用暫停執行。但顯然不是這樣!再次感謝.. – guskenny83

+0

不客氣:)你的項目祝你好運! – Josselin

相關問題