我如何将StringVar()放在StringVar()中?

时间:2016-01-23 02:07:44

标签: python tkinter

我并不完全确定如何表达这一点,但我正在创建一个包含一些ASCII艺术的Tkinter应用程序。部分是艺术,但部分是用户想要阅读的文本。原始文本艺术看起来像这样:

 _______________________________________
|                    .                  |
| +===================================+ |
| |                                   | |
| |                                   | |
| |                                   | |
| |                                   | |
| |                                   | |
| |                                   | |
| |                                   | |
| |                                   | |
| |                                   | |
| |                                   | |
| |                                   | |
| +===================================+ |
|_______________________________________|
\  +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+  \
|\  \__\__\__\__\__\__\__\__\__\__\_____  \
\ \  \___\__\__\__\__\__\__\__\__\__\____  \
 \ \  \____\__\__\__\__\__\__\__\__\______  \
  \ \  \______\__\__\__\__\__\__\__\_______  \
   \ \  \__\__\__\_________________\__\_____  \
    \ \                                        \
     \ \                                        \
      \ \                                        \
       \ \________________________________________\
        \|________________________________________|

然而,除了屏幕上的35个空格外,我每行有9 %s个,除了第一个和最后一个,两边各有两个空格,每个都有31个字符。 (看起来这是一个变量):

comp = r"""
 _______________________________________
|                    .                  |
| +===================================+ |
| |                                   | |
| |  %s  | |
| |  %s  | |
| |  %s  | |
| |  %s  | |
| |  %s  | |
| |  %s  | |
| |  %s  | |
| |  %s  | |
| |  %s  | |
| |                                   | |
| +===================================+ |
|_______________________________________|
\  +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+  \
|\  \__\__\__\__\__\__\__\__\__\__\_____  \
\ \  \___\__\__\__\__\__\__\__\__\__\____  \
 \ \  \____\__\__\__\__\__\__\__\__\______  \
  \ \  \______\__\__\__\__\__\__\__\_______  \
   \ \  \__\__\__\_________________\__\_____  \
    \ \                                        \
     \ \                                        \
      \ \                                        \
       \ \________________________________________\
        \|________________________________________|
"""

我还有一系列"屏幕"对于计算机,这些列表包含9个元素,每个元素正好有31个字符。下面是我在屏幕上显示内容的示例,假设ASCII计算机已经被定义为原始文本多行字符串,如上所述:

def change_screen():
    comp_art.set(comp % tuple(screen1))

blank = [" "*31, " "*31, " "*31, " "*31, " "*31, " "*31, " "*31, " "*31, " "*31]
screen1 = ["31 characters of text", "31 char..."]  #List with 9 elements


from tkinter import *
root = Tk()
root.option_add("*Label.Font", "courier")

comp_art = StringVar()
comp_art.set(comp % tuple(blank))

comp_label = Label(root, textvariable=comp_art, justify=LEFT)
change_button = Button(root, text="TEST", command=change_screen)
comp_label.pack()
change_button.pack()

root.mainloop()

运行时,此代码会生成一个带有空白计算机艺术和其下方按钮的窗口。按下按钮后,列表screen1中的文本将显示在计算机的屏幕上。这很好,但因为这是一个游戏,我想一次显示这样的消息。我尝试过定义第三个开始完全空白的列表,并在for循环中将列表中的每个元素从空白更改为文本,一次一个。它看起来像这样:

import time
def display(x): 
    # x is a list, like screen1 above, that I want to display one line at a time
    show_list = [x[0]]
    for _ in range(8):
        show_list.append(" "*31)
        # Makes the list 9 elements long, and all spaces except for the first
        # one, which is the first element of x, the one I want to display

    for n in range(x):
        comp_art.set(comp % tuple(show_list)
        time.sleep(0.5)
        show_list[n] = x[n]

该函数的后半部分,即第二个for循环,更改了我StringVar() comp_art,我之前分配给了一个Label。它始终使屏幕显示show_list的内容,但每次我更改show_list时,我也comp_art.set(),这反过来应该改变计算机的外观,因为它是与StringVar()关联的comp_label。但是,当我运行该代码时,它不起作用。它改变了计算机的显示,但不是一次只做一行,而是等待4.5秒(因为time.sleep(0.5)),而屏幕保持空白然后显示我的内容想要它。有谁知道为什么,或者我能做些什么不同的事情?尽管我付出了最大的努力,但我还是没有想到比这更有效的东西,因为如果我使用多个标签,那么它们之间就会存在差距,并且ASCII艺术已全部关闭。

我也想知道是否有办法解决问题?#34;筑巢" StringVar()秒。例如,当您在tkinter中定义标签并将其作为StringVar赋予textvariable时,标签将在变量更改时自动更新。有没有办法在StringVar()中添加StringVar(),这样当您更新一个StringVar()时,较大的一个会更新,如果是分配给标签,该标签将更新。有没有办法做到这一点? tkinter中的trace()函数会帮助我做到这一点,如果是的话,我会做什么?

对于这个问题的淫秽篇幅感到抱歉...感谢您花时间阅读它,并感谢您提供任何和所有答案。

编辑:我还做了几件事,包括编写四个独立的函数来编辑计算机的前四行,每个函数调用time.sleep(0.5)定义和打包后标签,但在root.mainloop()之前,我一次调用这些函数。然而,这样做会创建一个窗口,就像我想要的那样,但窗口保持完全黑色,直到四个功能成功运行,此时标签进入屏幕,所有四个更改的行。我想要的动画片段仍然无法正常工作。现在,我有一个名为comp_screen的第三个列表,它目前等于blank,但我可以更改。我还有一个函数update_screen(),它可以更新计算机StringVar()。我做错了什么?

comp_screen = blank

def update_screen():
    computer.set(art.comp % tuple(comp_screen))

def intro_f1():
    wait(0.5)
    comp_screen[0] = intro[0]
    update_comp()

def intro_f2():
    wait(0.5)
    comp_screen[1] = intro[1]
    update_comp()

def intro_f3():
    wait(0.5)
    comp_screen[2] = intro[2]
    update_comp()

def intro_f4():
    wait(0.5)
    comp_screen[3] = intro[3]
    update_comp()

# The Tk() code that makes the window and label (see above - no use typing
# it out again). I have not yet called mainloop().

intro_f1()
intro_f2()
intro_f3()
intro_f4()

root.mainloop()

1 个答案:

答案 0 :(得分:1)

你所拥有的display函数并不能满足你的需要,因为它在tkinter事件循环之外运行,它处理重绘屏幕之类的内容。当您的循环正在运行时,窗口的其余部分将停止,无法更新并显示您已设置的新文本。

因此,不是用一个等待这样的循环编写一个函数,而是需要编写一些可以重复调用的东西(可能来自一个计时器),并且每次都更新一行。

同样的一般想法也可能是您应该如何处理“嵌套StringVar”问题。不要试图让一个人直接包含另一个,而是编写一个从“内部”文本中提取文本的函数,并将其放在“外部”StringVar中的正确位置。然后在正确的时间调用该函数。