简体   繁体   English

Tkinter:create_window()和框架无法正确显示

[英]Tkinter: create_window() and frame not displayed correctly

I'm working on a small project with Python and Tkinter. 我正在使用Python和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) . 我将此框架放在Canvas对象中(使用create_window() ),该对象位于另一个框架中(与滚动条一起)

The problem is that I'm not able to visualise the table correctly; 问题是我无法正确显示表格。 I can only get the vertical part of it: 我只能得到它的垂直部分:

在此处输入图片说明

The green part is the frame containing the Canvas object and the scrollbar 绿色部分是包含Canvas对象和滚动条的框架

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: 我希望桌子具有固定的高度( 这正在工作 ),如您在此处看到的:

在此处输入图片说明

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. 红色部分是包含表的canvas对象,绿色部分是包含画布和滚动条的框架。 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. 问题在于canvas对象没有展开( 请参见上一个屏幕截图 ,我不知道为什么。 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

Try adding this to your table creating code right after tab_space.grid( row = 0, column = 0) : 尝试将其添加到表中,然后在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. Tkinter grid几何管理器对小部件中的每一列和每一行都有一个“权重”。 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 . 例如,如果您有一个名为frame ,则frame.columnconfigure(3, weight=7) frame窗口小部件的第3列的权重设置为7。有一个对应的函数称为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. 默认权重为0,这意味着随着可用空间或所需空间的增加或减少,列/行不会增长或收缩-它们是静态的。 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. 如果第0列的权重为2,第1列的权重为3,并且有5个额外像素可用,则第0列将扩大2个像素,而第1列将扩大3个像素。

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. 这是有关NMT的columnconfigurerowconfigure函数的一些文档 Point of interest: columnconfigure and rowconfigure are actually aliases of grid_columnconfigure and grid_rowconfigure , implemented, I assume, to save 5 keystrokes. 兴趣点: columnconfigurerowconfigure实际上是grid_columnconfiguregrid_rowconfigure别名,我假设要实现以节省5次击键。

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. 我认为您将必须使用<Configure>事件来做一些工作,以使窗口自动调整为正确的宽度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM