Tkinter: Как сделать фиксированный размер холста с помощью полос прокрутки, которые изменяют размер окна - PullRequest
1 голос
/ 14 мая 2019

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

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

Я сделал цвет фона черным, чтобы четко видеть область холста.


import tkinter as tk
from tkinter import *


class DialogueCreation(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.xbar = tk.Scrollbar(parent, orient=HORIZONTAL)
        self.xbar.pack(side=BOTTOM, fill=X)

        self.ybar = tk.Scrollbar(parent)
        self.ybar.pack(side=RIGHT, fill=Y)

        self.item_canvas = tk.Canvas(parent, width=5000, height=5000, xscrollcommand=self.xbar.set, yscrollcommand=self.ybar.set)
        self.item_canvas.pack(side=LEFT, expand=FALSE, fill=None)
        self.item_canvas.configure(background='black')


if __name__ == '__main__':
    root = tk.Tk()
    DialogueCreation(root)
    root.title("Editor")
    root.mainloop()


Размер холста 5000х5000, поэтому я определенно должен иметь возможность прокручиваться, когда окно маленькое.Я хочу, чтобы полосы прокрутки оставались на одном уровне с краями окна, не меняя размер холста.Полосы прокрутки остаются неактивными независимо от того, насколько велико или мало окно.Я предполагаю, что холст изменяет размеры с окном, что определенно не является желаемым результатом.

В конечном итоге на этом холсте будет отображаться несколько изображений, и расположение этих изображений не должно изменяться на холсте.Я не верю, что проблема в том, как я связал полосы прокрутки (я проверил несколько других постов на этом сайте, чтобы убедиться в этом), но это было бы нехарактерно, если бы я пропустил что-то очевидное подобное.

1 Ответ

0 голосов
/ 14 мая 2019

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

Для этого вам нужно установить атрибут scrollregion в области рисования.Вы используете атрибуты width и height, чтобы установить размер видимой части холста.

Кроме того, подключение полос прокрутки - это улица с двусторонним движением: вы должны настроить холст для обновленияполосы прокрутки и настройте полосы прокрутки для прокрутки холста.

Примечание : вы сделали DialogCreation a Frame, но все виджеты помещаются непосредственно в родительский элемент.Это очень необычно и не лучший способ сделать это.Я рекомендую наследовать от Frame, как вы, но тогда все виджеты должны идти в self, а не в родительском.

Когда вы делаете это таким образом, вы должны обязательно позвонить pack в случае DialogCreation, например:

dr = DialogueCreation(root)
dr.pack(fill="both", expand=True)

Использование пакета

С pack вы должны установить опцию expand на True, если вы хотите, чтобы видимая часть увеличивалась или уменьшалась при изменении размера окна пользователем.

Мой личный опыт заключается в том, что код легче понятьи легче поддерживать, если вы отделяете создание виджета от макета виджета.Следующий код показывает, как я переписал бы ваш код, используя pack.Обратите внимание на дополнительные строки для настройки xbar и ybar, а также настройки scrollregion.

class DialogueCreation(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.xbar = tk.Scrollbar(self, orient=HORIZONTAL)
        self.ybar = tk.Scrollbar(self)
        self.item_canvas = tk.Canvas(self, width=400, height=400,
                                     xscrollcommand=self.xbar.set,
                                     yscrollcommand=self.ybar.set)

        self.xbar.configure(command=self.item_canvas.xview)
        self.ybar.configure(command=self.item_canvas.yview)

        self.item_canvas.configure(scrollregion=(0,0,4999,4999))
        self.item_canvas.configure(background='black')

        self.xbar.pack(side=BOTTOM, fill=X)
        self.ybar.pack(side=RIGHT, fill=Y)
        self.item_canvas.pack(side=LEFT, expand=TRUE, fill=BOTH)

Использование сетки

Очевидная проблема с .grid заключается в том, что он просто помещает полосы прокрутки рядом с холстом.

Iне вижу в этом ничего очевидного.grid не имеет такого ограничения.Вы можете разместить полосу прокрутки в любом месте.

При использовании grid важно помнить, что строки и столбцы не растут и не уменьшаются автоматически, когда окно в целом меняет размер.Вы должны явно указать tkinter, какие строки и столбцы нужно увеличивать или уменьшать.

Чтобы добиться того же эффекта, что и при использовании pack, вам необходимо настроить нулевую строку, нулевой столбец, чтобы получить все дополнительное пространство.Вы делаете это, давая им weight больше нуля.

Чтобы использовать grid вместо pack, замените последние три строки приведенного выше примера следующими шестью строками:

self.item_canvas.grid(row=0, column=0, sticky="nsew")
self.xbar.grid(row=1, column=0, sticky="ew")
self.ybar.grid(row=0, column=1, sticky="ns")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
...