簡體   English   中英

在tkinter treeview中的行內換行

[英]Wrap text inside row in tkinter treeview

可以使用tkinter treeview將文本換行嗎? 我試圖更改行高,但文本不會自動換行。 基本上我想在行中有多行文本。

這是代碼:

from tkinter import*
from tkinter import ttk

myApp = Tk()


NewTree= ttk.Treeview(myApp, height=5)
NewTree['show'] = 'headings'
s = ttk.Style()
s.configure('Treeview', rowheight=40)

NewTree["columns"]=("1","2")

NewTree.column("1", width=60)
NewTree.column("2", width=60)

NewTree.heading("1", text="col a")
NewTree.heading("2", text="col b")

item = NewTree.insert("", "end", values=("i want to wrap this text","and this text"))

NewTree.grid(row=0,column=0)

myApp.mainloop()

這是第二版代碼(當您可以在treeview中手動添加項目時),它只是我上面發布的代碼之前的一個大功能。 我試圖將不同的值放在lenght但結果是相同的(不會自動換行):

from tkinter import*
from tkinter import ttk
from tkinter import messagebox

import textwrap

def wrap(string, lenght=15):
    return '\n'.join(textwrap.wrap(string, lenght))

myApp = Tk()

def editact(event):

    def double(event): # funkcija koja kreira celiju kada se klikne dupli klik
        try:            
            if NewTree.identify_region(event.x, event.y) == 'cell':
                # the user clicked on a cell

                def ok(event):
                    """Change item value."""
                    NewTree.set(item, column, entry.get())
                    entry.destroy()

                column = NewTree.identify_column(event.x)  # identify column
                item = NewTree.identify_row(event.y)  # identify item
                x, y, width, height = NewTree.bbox(item, column) 
                value = NewTree.set(item, column)

            elif NewTree.identify_region(event.x, event.y) == 'heading': 
                    # the user clicked on a heading

                def ok(event):
                    """Change heading text."""
                    NewTree.heading(column, text=entry.get())
                    entry.destroy()

                column = NewTree.identify_column(event.x) # identify column
                # tree.bbox work only with items so we have to get the bbox of the heading differently
                x, y, width, _ = NewTree.bbox(NewTree.get_children('')[0], column) # get x and width (same as the one of any cell in the column)
                # get vertical coordinates (y1, y2)
                y2 = y
                # get bottom coordinate
                while NewTree.identify_region(event.x, y2) != 'heading':  
                    y2 -= 1
                # get top coordinate
                y1 = y2
                while NewTree.identify_region(event.x, y1) == 'heading':
                    y1 -= 1
                height = y2 - y1
                y = y1
                value = NewTree.heading(column, 'text')

            elif NewTree.identify_region(event.x, event.y) == 'nothing': 
                column = NewTree.identify_column(event.x) # identify column
                # check whether we are below the last row:
                x, y, width, height = NewTree.bbox(NewTree.get_children('')[-1], column)
                if event.y > y:

                    def ok(event):
                        """Change item value."""
                        # create item
                        item = NewTree.insert("", "end", values=("", ""))
                        NewTree.set(item, column, entry.get())
                        entry.destroy()

                    y += height
                    value = ""
                else:
                    return
            else:
                return

            # display the Entry   
            entry = ttk.Entry(NewTree)  # create edition entry
            entry.place(x=x, y=y, width=width, height=height, anchor='nw')  # display entry on top of cell
            entry.insert(0, value)  # put former value in entry
            entry.bind('<FocusOut>', ok)  #validate when you click on other cell

            entry.focus_set()

        except IndexError:

            Error=messagebox.showinfo("Error!","You have 0 rows. Please add a new row.")
            sys.exit() #za resavalje greske`
            pass

    NewTree.bind('<Double-Button-1>', double) #create new cell with double click


NewTree= ttk.Treeview(myApp, height=5)
NewTree['show'] = 'headings'

s = ttk.Style()
s.configure('Treeview', rowheight=60)

NewTree["columns"]=("1","2")

NewTree.column("1", width=100, anchor="center")
NewTree.column("2", width=100, anchor="w")

NewTree.heading("1", text="Col A")
NewTree.heading("2", text="Col B")


item = NewTree.insert("", "end", values=(wrap(""),wrap("")))
NewTree.item(item, tags=item)
NewTree.bind('<1>', editact)

NewTree.grid(row=0,column=0, columnspan=5, padx=5)

myApp.mainloop()

以下代碼使用<B1-Motion>事件動態包裝文本(因此,支持調整列的大小,並且文本將相應地“包裝”)。

from tkinter import Tk, ttk
from tkinter.font import Font
from functools import partial

myApp = Tk()

NewTree= ttk.Treeview(myApp, height=5)
NewTree['show'] = 'headings'
s = ttk.Style()
s.configure('Treeview', rowheight=50)

NewTree["columns"]=("1","2")

NewTree.column("1", width=80, anchor="nw")
NewTree.column("2", width=80, anchor="nw")

NewTree.heading("1", text="col a")
NewTree.heading("2", text="col b")

item = NewTree.insert("", "end", values=("i want to wrap this text","and this text"))
print(item)

NewTree.grid(row=0,column=0)

def motion_handler(tree, event):
    f = Font(font='TkDefaultFont')
    # A helper function that will wrap a given value based on column width
    def adjust_newlines(val, width, pad=10):
        if not isinstance(val, str):
            return val
        else:
            words = val.split()
            lines = [[],]
            for word in words:
                line = lines[-1] + [word,]
                if f.measure(' '.join(line)) < (width - pad):
                    lines[-1].append(word)
                else:
                    lines[-1] = ' '.join(lines[-1])
                    lines.append([word,])

            if isinstance(lines[-1], list):
                lines[-1] = ' '.join(lines[-1])

            return '\n'.join(lines)

    if (event is None) or (tree.identify_region(event.x, event.y) == "separator"):
        # You may be able to use this to only adjust the two columns that you care about
        # print(tree.identify_column(event.x))

        col_widths = [tree.column(cid)['width'] for cid in tree['columns']]

        for iid in tree.get_children():
            new_vals = []
            for (v,w) in zip(tree.item(iid)['values'], col_widths):
                new_vals.append(adjust_newlines(v, w))
            tree.item(iid, values=new_vals)


NewTree.bind('<B1-Motion>', partial(motion_handler, NewTree))
motion_handler(NewTree, None)   # Perform initial wrapping

myApp.mainloop()

分隔符向左移動 分隔符向右移動

您可以使用textwrap模塊定義此wrap功能:

def wrap(string, lenght=8):
    return '\n'.join(textwrap.wrap(string, lenght))

現在,你可以更換item是:

item = NewTree.insert("", "end", values=(wrap("i want to wrap this text"),
                                         wrap("and this text")))

完整代碼

from tkinter import *
from tkinter import ttk

import textwrap


def wrap(string, lenght=8):
    return '\n'.join(textwrap.wrap(string, lenght))


myApp = Tk()

NewTree = ttk.Treeview(myApp, height=5)
NewTree['show'] = 'headings'
s = ttk.Style()
s.configure('Treeview', rowheight=40)

NewTree["columns"] = ("1", "2")

NewTree.column("1", width=60)
NewTree.column("2", width=60)

NewTree.heading("1", text="col a")
NewTree.heading("2", text="col b")

item = NewTree.insert("", "end", values=(wrap("i want to wrap this text"),
                                         wrap("and this text")))

NewTree.grid(row=0, column=0)

myApp.mainloop()

輸出量

輸出量

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM