Как сделать так, чтобы прокрутка Python могла прокручиваться и автоматически изменять размер холста, используя сетку вместо пакета? - PullRequest
0 голосов
/ 18 апреля 2019

Я пытаюсь сделать виджеты в моем холсте прокручиваемыми, и холст / виджеты автоматически меняют размеры.

В моем коде у меня есть "canvas.create_window ((0, 0), window = new_frame,anchor = 'nw') "закомментировано.Выполнение этого способа приведет к автоматическому изменению размера виджетов, но полоса прокрутки не будет работать.

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

Я не могу найти решение, где используется .grid ().Решение будет оценено.

import tkinter as tk
from tkinter import *
from tkinter import ttk


def on_mousewheel(event):
    canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")

def on_configure(event):
    # update scrollregion after starting 'mainloop'
    # when all widgets are in canvas
    canvas.configure(scrollregion=canvas.bbox('all'))

# Create new window
new_win = tk.Tk()
new_win.focus_force()

# Create a canvas with a scrollbar
canvas = tk.Canvas(new_win)
canvas.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)

scrollbar = ttk.Scrollbar(new_win, command=canvas.yview)
scrollbar.grid(sticky=(N, S), row=0, column=1)
canvas.config(yscrollcommand=scrollbar.set)

# --- put frame in canvas ---
new_frame = tk.Frame(canvas)
new_frame.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)

# canvas.create_window((0, 0), window=new_frame, anchor='nw')

# update scrollregion after starting 'mainloop'
# when all widgets are in canvas
canvas.bind('<Configure>', on_configure)
new_win.bind('<MouseWheel>', on_mousewheel)

# Add Widgets
label = tk.Label(new_frame, text="test")
label2 = tk.Label(new_frame, text="test")
label.grid(column=0, row=0, sticky=tk.N + tk.S + tk.E + tk.W)
label2.grid(column=0, row=1, sticky=tk.N + tk.S + tk.E + tk.W)


txt_box = tk.Text(new_frame)
txt_box2 = tk.Text(new_frame)
txt_box.grid(column=1, row=0, sticky=tk.N + tk.S + tk.E + tk.W)
txt_box2.grid(column=1, row=1, sticky=tk.N + tk.S + tk.E + tk.W)

# configure
new_win.grid_columnconfigure(0, weight=1)
new_win.grid_rowconfigure(0, weight=1)

new_frame.grid_columnconfigure(1, weight=1)
new_frame.grid_rowconfigure(0, weight=1)

canvas.grid_columnconfigure(0, weight=1)
canvas.grid_rowconfigure(0, weight=1)

new_win.mainloop()

1 Ответ

0 голосов
/ 22 апреля 2019

Прежде всего, единственный способ прокрутить что-либо на холсте - это поместить объект на холст с помощью одной из функций create_*. Если вы добавляете рамку к холсту с grid, она не может быть прокручена. Поэтому вам нужно удалить строку, которая вызывает grid на new_frame, и раскомментировать строку, которая вызывает create_window.

Когда вы встраиваете рамку в холст с помощью create_window, вы несете ответственность за поддержание размера виджета. В вашем случае вам нужно сбрасывать размер внутреннего фрейма всякий раз, когда сам холст меняет размер.

Поскольку у вас уже есть привязка к <Configure> на холсте, все, что вам нужно сделать, это настроить размер внутреннего фрейма на основе параметра width, переданного в объект события. Для этого вам нужно либо сохранить идентификатор созданного окна, либо присвоить созданному окну тег.

Давайте начнем с присвоения окну тега, который вы можете сделать при создании окна:

canvas.create_window((0, 0), window=new_frame, anchor='nw', tags=('internal_frame',))

Далее, сбросьте ширину этого фрейма, чтобы он соответствовал ширине вашего холста:

def on_configure(event):
    canvas.itemconfigure('internal_frame', width=event.width-10)
    ...

Примечание: чтобы помочь визуализировать то, что происходит во время отладки, он помогает придавать характерные фоновые цвета холсту, внутренней рамке и окну. Это также помогает добавить отступы или границы, чтобы вы могли видеть, где заканчивается один виджет и начинается другой.

...