Обтекание текста внутри строки в древовидной структуре tkinter - PullRequest
0 голосов
/ 02 июля 2018

Можно ли обернуть текст в строку, используя древовидную структуру tkinter? Я пытался изменить высоту строки, но текст не переносится. в основном я хочу иметь многострочный текст в строке.

Это код:

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()

Это вторая версия кода (когда вы можете вручную добавлять элементы в древовидную структуру). У него просто одна большая функция перед кодом, который я выложил выше. Я пытался поставить разные значения на 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()

Ответы [ 2 ]

0 голосов
/ 02 июля 2018

В следующем коде событие <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):
        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 NewTree['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()

Separator shifted left Separator shifted right

0 голосов
/ 02 июля 2018

Вы можете использовать модуль 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()

выход

Output

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...