2015-03-31 55 views
3

我正在編寫一個程序,它涉及在循環內的Tkinter畫布上的create_text()框中顯示一些文本。每個單詞顯示,然後由下一個替換。有點像閃存卡。如何在Tkinter畫布中爲子字符串着色

我需要爲每個單詞的一個字母上色,靠近單詞的中間,以便當用戶正在閱讀單詞時,他們的注意力集中在單詞的中間。所以if len(i)=1, color i[0], if len(i)>= 2 and <= 5, color i[1],等等。它需要使用Canvas,並使用

canvas.create_text(text = i[focus_index],fill = 'red') 

結果應打印這樣

exaMple 

來完成(但明顯的「M」將被染成紅色,而不是爲大寫)

+0

你就必須創建自己的方法來做到這一點,因爲create_text只需要一個單一的顏色作爲參數,我建議你看一下的方式來對測量文本的大小然後編寫一個方法,將字符串分解並用各自的顏色分別創建各自的顏色 – 2015-03-31 13:56:56

+0

如果這只是爲了告訴用戶在哪裏盯着,爲什麼不只是在文本中放置一個彩色點? – 2015-03-31 13:59:16

+0

所以它是一個速讀器程序,模仿Spritz部件。快速閱讀策略包括將注意力集中在單詞的中間,並將整個單詞用外圍信息處理到大腦中。我需要用這個「焦點」來表達這個單詞,它是一個字母中間的字母,其顏色與其他文字不同。我避免使用單詞突出顯示,因爲Tkinter中有一個突出顯示()方法可以執行其他操作 – zachcapp 2015-03-31 14:56:36

回答

1

我假設你想要類似this

這是我現在可以得到的最接近的。它創建三個文本框並使用anchor屬性將它們保持在正確的位置。儘管如此,它對於非常寬或窄的字母來說效果不佳。這並不完美,但可能是一個開始。

import Tkinter as tk 

root = tk.Tk() 

c = tk.Canvas(root) 
c.pack(expand=1, fill=tk.BOTH) 

words = '''I am writing a program that involves displaying some text in a create_text() box on a Tkinter canvas, within a loop. Each word is displayed, then replaced by the next. Sort of like flash cards. I need to color one letter of each word, close to the middle of the word, so that when the user is reading the words their eyes focus on the middle of the word. So if len(i)=1, color i[0], if len(i)>= 2 and <= 5, color i[1], and so on. It needs to be done using the Canvas, and using canvas.create_text(text = i[focus_index],fill = 'red') The result should print like this exaMple (but obviously "m" would be colored red, not be uppercase)''' 
words = words.split() 

def new_word(i): 
    if i == len(words): 
     i = 0 

    word = words[i] 
    middle = (len(word)+1)//2 
    c.itemconfigure(t1, text=word[:middle-1]+' ') 
    c.itemconfigure(t2, text=word[middle-1:middle]) 
    c.itemconfigure(t3, text=word[middle:]) 

    root.after(100, lambda: new_word(i+1)) 


t1 = c.create_text(200,100,text='', anchor='e', font=("Courier", 25)) 
t2 = c.create_text(200,100,text='', anchor='e', font=("Courier", 25), fill='red') 
t3 = c.create_text(200,100,text='', anchor='w', font=("Courier", 25)) 
new_word(0) 

root.geometry('400x200+200+200') 
root.mainloop() 

好,利用Bryan Oakley's comment的鏈接,我提高了一些,以便它可以與任何字體,不僅那些等寬的代碼。代碼將彩色字母的中心保留在相同的位置,並將單詞的正面和背面放置在正確的距離。

import Tkinter as tk 
import tkFont 

root = tk.Tk() 
c = tk.Canvas(root) 
c.pack(expand=1, fill=tk.BOTH) 

fn = "Helvetica" 
fs = 24 
font = tkFont.Font(family=fn, size=fs) 

words = '''I am writing a program that involves displaying some text in a create_text() box on a Tkinter canvas, within a loop. Each word is displayed, then replaced by the next. Sort of like flash cards. I need to color one letter of each word, close to the middle of the word, so that when the user is reading the words their eyes focus on the middle of the word. So if len(i)=1, color i[0], if len(i)>= 2 and <= 5, color i[1], and so on. It needs to be done using the Canvas, and using canvas.create_text(text = i[focus_index],fill = 'red') The result should print like this exaMple (but obviously "m" would be colored red, not be uppercase)''' 
words = words.split() 

def new_word(i): 
    if i == len(words): 
     i = 0 

    word = words[i] 
    middle = (len(word)+1)//2 

    front = word[:middle-1] 
    letter = word[middle-1:middle] 
    back = word[middle:] 

    c.itemconfigure(t1, text=front) 
    c.itemconfigure(t2, text=letter) 
    c.itemconfigure(t3, text=back) 
    c.coords(t1, 200-font.measure(letter)/2, 100) 
    c.coords(t3, 200+font.measure(letter)/2, 100) 

    root.after(100, lambda: new_word(i+1)) 


t1 = c.create_text(200,100,text='', anchor='e', font=font) 
t2 = c.create_text(200,100,text='', anchor='c', font=font, fill='red') 
t3 = c.create_text(200,100,text='', anchor='w', font=font) 
new_word(0) 

root.geometry('400x200+200+200') 
root.mainloop() 
+0

是的,這可以很好地適應一些變化,但現在我無法得到它來刪除t1,t2,t3在提出下一個詞之前。它只是將它們堆疊在一起,這是我在程序的早期階段遇到的一個問題,但使用delete()方法運行良好 – zachcapp 2015-03-31 16:05:59

+0

這就是爲什麼我創建它們一次然後使用'itemconfigure'替換文本創建新的文本框。 – fhdrsdg 2015-03-31 16:11:25

+0

對!說得通。現在效果很好。我承諾的最後一個問題..字體是Courier,所以它是等寬字體,但是在紅色字母的兩邊似乎都有一個額外的空間區域,但是當我刪除每個子字符串中的空格時,以中間字母開頭和結尾。我如何解決這個問題,使整個單詞的間距相等? – zachcapp 2015-03-31 16:29:26

1

您無法將格式應用於畫布文本項目中的單個字符。您需要爲紅色字符創建一個不同的項目,然後做一些小算術以將其覆蓋在字符串的頂部。

如果你不使用畫布,我推薦一個文本小部件,因爲它很容易將格式應用於單個字符。下面是一個完整的工作示例:

import Tkinter as tk 

words = ''' 
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi mi leo, vulputate a consectetur in, congue sit amet elit. Fusce lacinia placerat mi, vitae maximus leo congue sed. Donec non diam dapibus, fringilla risus at, interdum sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. 
'''.strip().split() 

class Example(tk.Frame): 
    def __init__(self, parent): 
     tk.Frame.__init__(self, parent) 
     self.text = tk.Text(self, wrap=None, font="Helvetica 24", 
          highlightthickness=0) 
     self.text.pack(side="top", fill="x") 

     self.text.tag_configure("center", justify="center") 
     self.text.tag_configure("red", foreground="red") 

     self.show_words(0) 

    def show_words(self, index): 
     self.show_word(words[index]) 
     next = index + 1 if index < len(words)-1 else 0 
     self.after(200, self.show_words, next) 

    def show_word(self, word): 
     self.text.configure(state="normal") 
     self.text.delete("1.0", "end") 
     self.text.insert("1.0", word, "center") 
     offset = len(word)/2 
     self.text.tag_add("red", "1.0 + %sc" % offset) 
     self.text.configure(state="disabled") 

if __name__ == "__main__": 
    root = tk.Tk() 
    Example(root).pack(fill="both", expand=True) 
    root.mainloop() 
+0

謝謝我玩過這個,看起來更容易一些。對於這個項目,我需要使用畫布 – zachcapp 2015-03-31 16:27:21