Я пытаюсь создать простое приложение с графическим интерфейсом, используя Tkinter и Python.Приложение должно выглядеть примерно так
------------------------------
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()
Когда я устанавливаю h = None
в initUI
, я вижу, что объекты расширяются до целогоокно

Когда я устанавливаю h = 10
, я вижу, что ряды становятся тоньше, но они распределены по всему экрану.

И когда я устанавливаю h = 50
, я вижу только первую строку.

В идеале я хотел бы видеть что-то вроде с h = 10
, но один ряд под другим.Как мне этого добиться?