Древовидная рамка на холсте - PullRequest
0 голосов
/ 21 мая 2019

enter image description here У этого кода есть 2 проблемы:
1. Я не могу получить рамку дерева, чтобы заполнить весь холст (по вертикали)
2. Я не хочу, чтобы отображался первый столбец
Как я могу это исправить?

import os

import time
import datetime
from datetime import timedelta
from tkinter.constants import TRUE

try:
    import Tkinter as tk
    import tkFont
    import ttk

    from Tkconstants import CENTER, LEFT, N, E, W, S
    from Tkinter import StringVar
except ImportError: # py3k
    import tkinter as Tkinter
    import tkinter.font as tkFont
    import tkinter.ttk as ttk

    from tkinter.constants import CENTER, LEFT, N, E, W, S
    from tkinter import StringVar

GRID_BORDER_WIDTH = "1"

def populate_treeview(frame, my_column_headers, my_list):

    style = ttk.Style()
    style.configure("mystyle.Treeview", highlightthickness=0, bd=0, font=('Calibri', 11)) # Modify the font of the body
    style.configure("mystyle.Treeview.Heading", font=('Calibri', 13,'bold')) # Modify the font of the headings
    style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {'sticky': 'nswe'})]) # Remove the borders

    tree=ttk.Treeview(frame, style="mystyle.Treeview") # create the widget

    tree["columns"]=my_column_headers
    for i in range (0,26):
        tree.column(my_column_headers[i], width=50, minwidth=20, stretch=Tkinter.YES)

    for i in range (0,26):
        tree.heading(my_column_headers[i] ,text=my_column_headers[i], anchor=Tkinter.W)

    PARENT="" # top level
    i = 0
    for item in my_list:
        #print ("item: " + str(item)) 
        tree.insert(PARENT, i, i, text=str(i), values=(item))
        i += 1

    tree.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=TRUE)

def OnFrameConfigure(canvas):
    '''Reset the scroll region to encompass the inner frame'''
    canvas.configure(scrollregion=canvas.bbox("all"))

def OnCanvasConfigure(self, event):
    width = 0
    for child in self.sensorsStatsFrame.grid_slaves():
        width += child.winfo_reqwidth()

    self.canvas.itemconfigure(self.canvas_frame, width=width, height=event.height)

# main ########################################################################
def main():

    print ("[DEBUG]***  Display Test***)\n");

    # Data
    item_column_headers =  ["a", "b", "c", "d","e", "f", "g", "h","i", "j", "k", "l","m", "n", "o", "p","q", "r", "s", "t", "u","v", "w", "x", "y", "z"]
    item_list = []
    for row_number in range (0,50):
        row = []
        for alpha in item_column_headers:
            row.append (str(row_number) + alpha)
        item_list.append(row)

    print (item_list)

    ## GUI ------------------------------------------------------------------------------

    root = Tkinter.Tk()

    canvas = Tkinter.Canvas(root, borderwidth=6, background="#222222" )

    frame = Tkinter.Frame(canvas, background="#ff0000", borderwidth = 5)
    frame.pack(side=Tkinter.TOP, expand=1, fill=Tkinter.BOTH)
    canvas.create_window((0,0), window = frame, anchor="nw", tags="my_tag")
    canvas.bind("<Configure>", lambda event,  root=root:OnCanvasConfigure(root))

    verticalScrollbar = Tkinter.Scrollbar(root, orient="vertical", command=canvas.yview)
    canvas.configure(yscrollcommand=verticalScrollbar.set)
    verticalScrollbar.pack(side="right", fill="y", expand=0)

    horizontalScrollbar = Tkinter.Scrollbar(root, orient="horizontal", command=canvas.xview)
    canvas.configure(xscrollcommand=horizontalScrollbar.set)
    horizontalScrollbar.pack(side="bottom", fill="x", expand=0)

    canvas.pack(fill="both", expand=1)

    frame.bind("<Configure>", lambda event, canvas=canvas: OnFrameConfigure(canvas))
    #frame.bind("<Configure>", OnFrameConfigure)

    populate_treeview(frame, item_column_headers, item_list) 

    root.geometry("1000x600")
    root.wm_title("Display Test")

    root.mainloop()

    print ("\n*** Done " + str(datetime.datetime.now()) + "  - Display Test ***");

# main ###############################################################################

if __name__ == "__main__":
    # stuff only to run when not called via 'import' here
    main()

Вот код с исправлениями, предложенными @BryanOakley

import os

import time
import datetime
from datetime import timedelta
from tkinter.constants import TRUE

try:
    import Tkinter as tk
    import tkFont
    import ttk

    from Tkconstants import CENTER, LEFT, N, E, W, S
    from Tkinter import StringVar
except ImportError: # py3k
    import tkinter as Tkinter
    import tkinter.font as tkFont
    import tkinter.ttk as ttk

    from tkinter.constants import CENTER, LEFT, N, E, W, S
    from tkinter import StringVar

GRID_BORDER_WIDTH = "1"

def populate_treeview(frame, my_column_headers, my_list):

    style = ttk.Style()
    style.configure("mystyle.Treeview", highlightthickness=0, bd=0, font=('Calibri', 11)) # Modify the font of the body
    style.configure("mystyle.Treeview.Heading", font=('Calibri', 13,'bold')) # Modify the font of the headings
    style.layout("mystyle.Treeview", [('mystyle.Treeview.treearea', {'sticky': 'nswe'})]) # Remove the borders

    tree=ttk.Treeview(frame, style="mystyle.Treeview") # create the widget

    vsb = ttk.Scrollbar(tree, orient="vertical", command=tree.yview)
    vsb.configure(command=tree.yview)
    vsb.pack(side='right', fill='y')
    tree.configure(yscrollcommand=vsb.set)

    hsb = ttk.Scrollbar(tree, orient="horizontal", command=tree.xview)
    hsb.configure(command=tree.xview)
    hsb.pack(side='bottom', fill='x')
    tree.configure(xscrollcommand=hsb.set)

    tree["columns"]=my_column_headers

    for i in range (0,26):
        tree.column(my_column_headers[i], width=50, minwidth=20, stretch=Tkinter.YES)

    for i in range (0,26):
        tree.heading(my_column_headers[i] ,text=my_column_headers[i], anchor=Tkinter.W)

    PARENT="" # top level
    i = 0
    for item in my_list:
        #print ("item: " + str(item)) 
        tree.insert(PARENT, i, i, text=str(i), values=(item))
        i += 1

    tree["show"] = ["headings"]        
    tree.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=TRUE)

# main ########################################################################
def main():

    print ("[DEBUG]***  Display Test***)\n");

    # Data
    item_column_headers =  ["a", "b", "c", "d","e", "f", "g", "h","i", "j", "k", "l","m", "n", "o", "p","q", "r", "s", "t", "u","v", "w", "x", "y", "z"]
    item_list = []
    for row_number in range (0,50):
        row = []
        for alpha in item_column_headers:
            row.append (str(row_number) + alpha)
        item_list.append(row)

    ## GUI ------------------------------------------------------------------------------

    root = Tkinter.Tk()

    frame = Tkinter.Frame(root, background="#ff0000", borderwidth = 5)
    frame.pack(side=Tkinter.TOP, expand=1, fill=Tkinter.BOTH)

    populate_treeview(frame, item_column_headers, item_list) 

    root.geometry("1000x600")
    root.wm_title("Display Test")

    root.mainloop()

    print ("\n*** Done " + str(datetime.datetime.now()) + "  - Display Test ***");

# main ###############################################################################

if __name__ == "__main__":
    # stuff only to run when not called via 'import' here
    main()

1 Ответ

2 голосов
/ 21 мая 2019

Я не могу заставить рамку просмотра дерева заполнить весь холст (по вертикали)

Проблема с деревом, не заполняющим холст, состоит в том, что оно находится в рамке, а рамка не заполняет холст. Похоже, что вы пытаетесь решить эту проблему в вашем OnCanvasConfigure методе, но есть много ошибок, мешающих его работе.

Во-первых, у вас есть цикл, который повторяется по self.sensorsStatsFrame.grid_slaves(), но вы не определили self, и нет виджета с именем sensorsStatsFrame, поэтому эта функция завершится ошибкой, прежде чем она получит возможность изменить высоту Рамка. Поскольку этот код выдает ошибку, последующий код в функции не будет запущен.

Далее вы пытаетесь вызвать self.canvas.configure, но опять-таки нет self и self.canvas, так что это утверждение не будет выполнено. Вы также используете self.canvas_frame, но, опять же, этого не существует, поэтому код не будет работать.

Если вы исправите все эти проблемы, код должен позволить рамке быть настроенной на ту же ширину и высоту, что и холст, решая первую проблему, о которой вы спрашиваете.

Я не хочу, чтобы отображался первый столбец

Атрибут treeview show позволяет вам определить, какие части дерева показывать. Вы назначаете ему список, который содержит "tree" и / или "headings". Вы не хотите видеть первый столбец, который представлен "tree". Таким образом, чтобы скрыть это значение, вы хотите передать "headings" как единственное значение в списке, используемое для атрибута show.

tree["show"] = ["headings"]
...