rss_ed
rss_ed

Reputation: 38

Tkinter: create_window() and frame not displayed correctly

I'm working on a small project with Python and Tkinter. I need to display a table with all the features of some excavators/digging machines.

The table is basically a big frame with lots of label objects inside of it. I'm putting this frame inside a Canvas object (using create_window()) which is inside another frame (together with a scrollbar).

The problem is that I'm not able to visualise the table correctly; I can only get the vertical part of it:

enter image description here

The green part is the frame containing the Canvas object and the scrollbar

The only way I found to solve the problem is using fixed widths...but it's not great. Any suggestions?

EDITED:

I want the table to have a fixed height ( and this is working ), as you can see here:

enter image description here

The red part is the canvas object, which contains the table, and the green part is the frame, which contains the canvas and the scrollbar. I've removed the scrollbar so it's easier to see what's going on.

The problem is that the canvas object is not expanding ( see the previous screenshot ) and I don't know why. What I'd like to have is that the width of the canvas follows the width of the table.

The code is here:

#!/usr/bin/env python
# -*- coding: utf-8 -*- 

import Tkinter, string, table
from functions import *

bg_color = "#d3d3d3"
first_table = True

# MODEL: Functions to handle the main processing of the program in
# response to user interaction
def create_tables():
    global tab, first_table, tab_space, mbtext
    select = choice.get()
    choices = [ 1, 2, 3, 4, 5]
    mbtext.set( str( choices[select])) # resetting the number in the menubutton
    if not first_table:
        # cleaning the canvas
        t.destroy()
        comp_space.destroy()
    # space to display the objects
    master = Tkinter.Frame( top, bg = 'green')
    master.grid( row = 2, column = 0, sticky = "wesn", padx = 10  )

    # space for the table:
    tab_space = Tkinter.Canvas( master, bg = 'red', highlightthickness = 0, height = 600, scrollregion=(0, 0, 2000, 780))
    tab_space.grid( row = 0, column = 0)

    # creating the table...
    tab = table.CompTable( tab_space, columns = choices[select]+1 )
    tab.first_set()
    tab_space.create_window(0, 0, anchor = "nw", window = tab)

    # and the scrollbar:
    scrollY = Tkinter.Scrollbar ( master, bg = bg_color, bd = 4, activebackground = bg_color, orient = "vertical")
    scrollY.grid( row = 0, column = 1, sticky = "nswe")

    #binding canvas and scrollbar together
    scrollY.configure( command = tab_space.yview)
    tab_space.configure(yscrollcommand = scrollY.set )

# VIEW: Setup the widgets

# The main window
top = Tkinter.Tk()
top.configure( bg = bg_color)
top.title("Comparatore")

# logo_frame/canvas - using a Canvas object to load images
logo_canvas = Tkinter.Canvas( top,  bg = bg_color, highlightthickness = 0, height = 58, width = 590 )
logo_canvas.grid( row = 0, column = 0, ipadx = 0, ipady=0, sticky = "nw")
logo = Tkinter.PhotoImage(file = "Images/Logo.gif")
logo_canvas.create_image(0, 0, image = logo, anchor="nw")

# background
bg_label = Tkinter.Label( top, bg = bg_color )
bg_label.grid( row = 1, column = 0, sticky = "nesw")

# menu to handle how many items we are using
select_text = Tkinter.Label( bg_label, text = " Selezionare il numero di macchine da confrontare: ", 
        font = ("verdana", 16), bg = bg_color)
select_text.grid( row = 0, column = 0, sticky = "nsew")

mbtext = Tkinter.StringVar()
mbtext.set("")
how_many_mb = Tkinter.Menubutton( bg_label, textvariable = mbtext, relief= "raised", bg = bg_color)
how_many_mb.menu = Tkinter.Menu( how_many_mb, tearoff = 0)
how_many_mb["menu"] = how_many_mb.menu
how_many_mb.grid( row = 0, column = 1, sticky = "nsew", padx = 4, ipadx = 18)

# CONTROLLER
choice = Tkinter.IntVar()
how_many_mb.menu.add_radiobutton( label = "1", variable = choice, value = 0, command = create_tables)
how_many_mb.menu.add_radiobutton( label = "2", variable = choice, value = 1, command = create_tables)
how_many_mb.menu.add_radiobutton( label = "3", variable = choice, value = 2, command = create_tables)
how_many_mb.menu.add_radiobutton( label = "4", variable = choice, value = 3, command = create_tables)
how_many_mb.menu.add_radiobutton( label = "5", variable = choice, value = 4, command = create_tables)


##
Tkinter.mainloop()

And this is the code of the table module:

#!/usr/bin/env python
# -*- coding: utf-8 -*- 

import Tkinter as tk

mbtext1 = tk.StringVar()
mbtext1.set("-Selezionare-")


details = ["Costruttore", "Modello", "Capacità Benna", "Carico rib. art.", "Peso", "Potenza",
                "Motore (Marca)", "Cilindrata", "Cilindri", "Alesaggio per corsa", "Regime di taratura",
                "Alimentazione aria", "Pompe", "Portata", "Pressione", "Trasmissione", "Marce",
                "Velocità traslazione", "Velocità di rotazione", "Differenziali", "Freni", "Pneumatici", "Passo", "Carreggiata",
                "Articolazione", " Raggio sterzo alla benna ", "Cinematismo benna", "Max altezza perno b.",
                "Forza di strappo", "Forza di penetrazione", "Sbalzo posteriore torretta", "Lama", "Larghezza benna", 
                "Larghezza max", "Altezza trasporto", "Larghezza cingoli", "Larghezza torretta",
                "Larghezza esterna pneumatici", "Lunghezza trasporto"]

class CompTable(tk.Frame):
    global details

    def __init__(self, parent, rows=len(details), columns=2):
        # using black background
        tk.Frame.__init__(self, parent, background="black")
        self._widgets = []
        for row in range(rows):
            current_row = []
            for column in range(columns):
                if row in [ 0, 1] and column != 0:
                    menu = tk.Menubutton(self, textvariable = mbtext1, width = 15)
                    menu.grid( row=row, column=column, sticky="nsew", padx=1, pady=1 )
                    current_row.append(menu)
                else:
                    label = tk.Label(self, background = "#fcfcfc", text="                           ", 
                                     borderwidth=0)
                    label.grid( row=row, column=column, sticky="nsew", padx=1, pady=1)
                    current_row.append(label)
            self._widgets.append(current_row)

    def set(self, row, column, value):
        widget = self._widgets[row][column]
        widget.configure(text=value)

    def first_set( self ):
        actual_detail = 0
        for element in details:
            self.set(actual_detail, 0, element)
            actual_detail += 1

Upvotes: 1

Views: 5662

Answers (1)

Brionius
Brionius

Reputation: 14098

Try adding this to your table creating code right after tab_space.grid( row = 0, column = 0):

master.columnconfigure(0, weight=1)

EDIT

Ok, this more or less solves the problem as stated:

If you replace

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

with

tab_space.grid( row = 0, column = 0, sticky="nsew")
top.columnconfigure(0, weight=1)
master.columnconfigure(0, weight=1)

Explanation:

The Tkinter grid geometry manager has a 'weight' for every column and row within a widget. The weight of a column/row determines how much of the widget's allotted space that column or row takes up.

You can change the weight of a given column/row. For example, if you have a frame called frame, then frame.columnconfigure(3, weight=7) sets the weight of column 3 of the frame widget to be 7. There is a corresponding function called rowconfigure.

The default weight is 0, which means the columns/rows do not grow or shrink as more or less room becomes available or required - they're static. If column 0 has a weight of 2 and column 1 has a weight of 3, and 5 extra pixels become available, column 0 expands by 2 pixels, and column 1 expands by 3 pixels.

That last bit is irrelevant if you only have one column, but the important part for this problem is that the column that contains the table-canvas (and the column that contains the master frame) has a nonzero weight, so the grid geometry manager knows to allow it to expand or contract at all, rather than keep it at whatever width was was initially allocated.

Here is some documentation on the columnconfigure and rowconfigure functions from NMT. Point of interest: columnconfigure and rowconfigure are actually aliases of grid_columnconfigure and grid_rowconfigure, implemented, I assume, to save 5 keystrokes.

Notes:

You should be able to see the rest of your table by manually resizing the window. I think you're going to have to do some work using the <Configure> event to get the window to automatically resize to the correct width.

Upvotes: 3

Related Questions