如何在Tkinter画布中为子字符串着色

时间:2015-03-31 12:30:43

标签: python tkinter tkinter-canvas

我正在编写一个程序,它涉及在循环内的Tkinter画布上的create_text()框中显示一些文本。显示每个单词,然后替换为下一个单词。有点像闪存卡。

我需要为每个单词的一个字母着色,靠近单词的中间,以便当用户正在阅读单词时,他们的眼睛会集中在单词的中间。所以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”会被涂成红色,而不是大写)

2 个答案:

答案 0 :(得分: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()

答案 1 :(得分: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()