当前位置: 代码迷 >> python >> Tkinter-使用网格管理器设置高度
  详细解决方案

Tkinter-使用网格管理器设置高度

热度:74   发布时间:2023-07-16 10:24:49.0

我正在尝试使用Tkinter和Python构建简单的GUI应用程序。 该应用程序应该看起来差不多

------------------------------
Label-1 | Canvas-1
------------------------------
Label-2 | Canvas-2
------------------------------
Label-3 | Canvas-3
------------------------------
 . . .
Label-3 | Canvas-3
------------------------------
        | scrollbar-horizontal
------------------------------

滚动条应在所有Canvas对象上同时滚动。 我能够完成那部分,但是当我尝试为每一行设置高度时,我都遇到了问题。 基本上我希望第一行在另一行下并具有预定义的高度。 我决定使用网格管理器来实现这一目标。

下面是一个最小的示例:

import tkinter
import tkinter.font


class LineData(object):

    def __init__(self, desc, box):
        self.desc = desc
        self.box = box

class LinePlotter(object):

    def __init__(self, label, canvas, desc, box):
        self.label = label
        self.canvas = canvas
        self.desc = desc
        self.box = box

    def plot(self):
        self.label.set(self.desc)
        x1, y1 = self.box[0], 1
        x2, y2 = self.box[1], 20
        print(self.desc)
        print(x1, y1, x2, y2)
        print(x2+100, y1, x2+(x2-x1)+100, y2)
        self.canvas.create_rectangle(x1, y1, x2, y2, outline="#D1D0CE", 
                                     width=4, fill="#D1D0CE")

        self.canvas.create_rectangle(x2+100, y1, x2+(x2-x1)+100, y2, outline="#D1D0CE",
                                     width=4, fill="#D1D0CE")


class Plotter(tkinter.Frame):

    def __init__(self, parent, lines_data):
        super().__init__(parent)
        self.parent = parent
        self.lines_data = lines_data

    def set_scroll_bar(self):
        x1, y1, x2, y2 = self.canvases[0].bbox(tkinter.ALL)
        x1 = y1 = 0
        for c in self.canvases:
            t1, u1, t2, u2 = c.bbox(tkinter.ALL)
            x1 = min(x1, t1)
            x2 = max(x2, t2)
            y1 = min(y1, u1)
            y2 = max(y2, u2)

        print("final=", x1, y1, x2, y2)
        for c in self.canvases:
            c.config(scrollregion=(x1-5, y1-5, x2+5, y2+5))

    def xview(self, *args):
        for c in self.canvases:
            c.xview(*args)

    def initUI(self):

        self.scrollX = tkinter.Scrollbar(self, orient=tkinter.HORIZONTAL)

        self.scrollX['command'] = self.xview
        self.scrollX.grid(row=2, column=1, sticky='NSEW')

        self.canvases = []

        h = 10
        for row_idx, line_data in enumerate(self.lines_data):
            desc = tkinter.StringVar()
            font = tkinter.font.Font(size=11)
            label = tkinter.Label(self, textvariable=desc, font=font, 
                                  height=h)
            label.grid(row=row_idx, column=0, sticky=tkinter.W)

            canvas = tkinter.Canvas(self, bg='white', 
                                    xscrollcommand=self.scrollX.set, 
                                    height=h)

            line = LinePlotter(desc, canvas, line_data.desc, line_data.box)
            line.plot()

            canvas.grid(row=row_idx, column=1, sticky=tkinter.W)
            self.canvases.append(canvas)

        self.set_scroll_bar()

        self.pack(expand=True, fill=tkinter.X)


l1 = LineData("L1", (50, 60))
l2 = LineData("L2", (200, 250))

root = tkinter.Tk()

Plotter(root, [l1, l2]).initUI()
root.mainloop()  

当我在initUI设置h = None时,我看到对象正在扩展到整个窗口

当我将h = 10设置h = 10 ,我看到行越来越细,但它们一直分布在屏幕上。

当我设置h = 50 ,我只看到第一行。

理想情况下,我希望看到类似h = 10但在另一行下面一行的内容。 我该如何实现?

您的问题是, h在创建画布时代表像素,但是在配置标签时却代表行数。 用于一个或另一个,但不能同时使用。

假设您希望画布的高度为10像素,只需从标签上除去高度即可。 这将使标签尽可能小。 它将仍然高于10像素,但是您可以通过选择较小的字体来解决该问题。

当我简单地从标签上删除height=h ,我得到的结果是:

  相关解决方案