当前位置: 动力学知识库 > 问答 > 编程问答 >

python - Collapse / expand text in Text widget

问题描述:

I have a Text widget with ALOT of information being printed to it. Id like to have sections of it minimizable so I can hide information until I need it.

from tkinter import *

main = Tk()

list1 = ['blah', 'blah', 'blah', 'blah', 'blah', 'blah', "\n" 'blah', 'blah', 'blah', 'blah', 'blah', 'blah', "\n", 'blah', 'blah', 'blah', 'blah', 'blah', 'blah', "\n",'blah', 'blah', 'blah', 'blah', 'blah', 'blah' , "\n"]

list2 = ['blah', 'blah', 'blah', 'blah', 'blah', 'blah', "\n" 'blah', 'blah', 'blah', 'blah', 'blah', 'blah', "\n", 'blah', 'blah', 'blah', 'blah', 'blah', 'blah', "\n",'blah', 'blah', 'blah', 'blah', 'blah', 'blah' , "\n"]

list3 = ['blah', 'blah', 'blah', 'blah', 'blah', 'blah', "\n" 'blah', 'blah', 'blah', 'blah', 'blah', 'blah', "\n", 'blah', 'blah', 'blah', 'blah', 'blah', 'blah', "\n",'blah', 'blah', 'blah', 'blah', 'blah', 'blah' , "\n"]

textwin = Text(main, height=20, width=150)

textwin.grid(rowspan=5, columnspan=5)

textwin.config(state='normal')

textwin.insert('end', "+--------------------------------------------------------------------------------- \n")

textwin.insert('end', list1)

textwin.insert('end', "+--------------------------------------------------------------------------------- \n")

textwin.insert('end', list2)

textwin.insert('end', "+--------------------------------------------------------------------------------- \n")

textwin.insert('end', list3)

main.mainloop()

I tried placing a button in the Text widget but it shrinks the Text widget to the size of the button and nothing else is displayed. I looked into linking text so I could make the "+" run a function that would delete/hide the section of text but I only found hyperlink instructions.

If this is not doable in the Text widget i'm open to other ideas. Maybe i'll have to move everything to a tree view widget.

网友答案:

You can configure a text tag to hide a range of characters. You can then hide or show a range of characters by applying or removing this tag. If you want to insert a button into the text, you will need to use the window_create method of the text widget.

You'll have to write the code to apply or remove the tag. For example, you could tag the start of a block with "block_start" or "heading" or something like that, then add a double-click binding on that tag to find all of the code between it and the next heading, and then either add or remove the "hidden" tag. Or, you could embed a button widget that does the same thing.

To configure the tag:

textwin.tag_configure("hidden", elide=True)

To hide a block of text, where start and end represent the range of characters to hide:

textwin.tag_add("hidden", start, end)

To show a block of text, where start and end represent the range of characters to show:

textwin.tag_remove("hidden", start, end)

Example

The following code is a contrived example that lets you double-click a header to hide or show the text under the header:

import tkinter as tk
from tkinter import font

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, borderwidth=1, relief="sunken")

        self.text = tk.Text(self, borderwidth=0, highlightthickness=0, wrap="word")
        self.vsb = tk.Scrollbar(self, command=self.text.yview)
        self.text.configure(yscrollcommand=self.vsb.set)

        self.vsb.pack(side="right", fill="y")
        self.text.pack(side="left", fill="both", expand=True)

        self.text.tag_configure("hidden", elide=True)
        self.text.tag_configure("header", background="black", foreground="white", spacing1=10, spacing3=10)
        self.text.tag_bind("header", "<Double-1>", self._toggle_visibility)

        for i in range(3):
            self.text.insert("end", "Header %s\n" % i, "header")
            self.text.insert("end", "blah blah blah blah\nblah blah blah\n\n")

    def _toggle_visibility(self, event):
        block_start, block_end = self._get_block("insert")
        # is any of the text tagged with "hidden"? If so, show it
        next_hidden = self.text.tag_nextrange("hidden", block_start, block_end)
        if next_hidden:
            self.text.tag_remove("hidden", block_start, block_end)
        else:
            self.text.tag_add("hidden", block_start, block_end)


    def _get_block(self, index):
        '''return indicies after header, to next header or EOF'''
        start = self.text.index("%s lineend+1c" % index)
        next_header = self.text.tag_nextrange("header", start)
        if next_header:
            end = next_header[0]
        else:
            end = self.text.index("end-1c")
        return (start, end)

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()
分享给朋友:
您可能感兴趣的文章:
随机阅读: