Классы Python в сетевом менеджере Tkinter

У меня проблема либо с менеджером геометрии GRID Tkinter, либо с настраиваемыми классами, либо с обоими. Скорее всего оба. Вот код:

import sys
from tkinter import 

def main():
    app = App()
    app.master.title("Sample application")
    app.mainloop()

class App(Frame):
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.grid(sticky=N+S+E+W)

        top = self.winfo_toplevel()
        top.rowconfigure(0, weight=1)
        top.columnconfigure(0, weight=1)

        self.rowconfigure(1, weight=1)
        self.columnconfigure(0, weight=1)
        self.__createWidgets()

    def __createWidgets(self):
        self.f1 = Frame(self, height=100, width=200,
            bg='green')
        self.f1.grid(row=0, column=0, sticky=E+W)

        self.f2 = Frame( self, bg= "yellow", height=100, width=200 ) ############################# CHANGE to self.f2 = myTestFrame( self )
        self.f2.grid(row=1, sticky = N+S+E+W)

        self.f3 = Frame( self, bg = "cyan", height = 100, width = 200 )
        self.f3.grid(row=2, sticky = E+W)

        self.quitButton = Button ( self, text="Quit", command=self.quit )
        self.quitButton.grid(row=4, column=0, columnspan=100,
            sticky=E+W)

class myTestFrame( Frame ):
    def __init__( self, parent):
        Frame.__init__(self, None)

        self.myText = Text( self )
        self.myText.grid()

        #self.testFrame = Frame ( self, bg = "white", height = 100, width = 300 )
        #self.testFrame.grid()

if __name__ == "__main__":
    main()

`

Теперь вот проблема: этот фрагмент кода делает все, что я хочу. Здесь есть три кадра: верхний кадр self.f1, средний кадр self.f2, нижний кадр self.f3 и простая кнопка выхода. Верхний (строка 0) и нижний (строка 2) кадры изменяют размер по горизонтали (столбец 0), а строка среднего кадра (строка 1, столбец 0) получает весь вес для изменения размера по горизонтали и вертикали. Все хорошо ... ПОКА не пытаюсь реализовать свой класс myTestFrame.

Когда я пытаюсь заполнить настраиваемый фрейм в self.f2, скажем, Text() виджетом, все идет наперекосяк. Он отображает текстовый виджет по умолчанию, но мое изменение размера выглядит странно, размещение GRID - сумасшедшее. Что здесь происходит?

РЕДАКТИРОВАТЬ!!! Ответ unutbu ниже, безусловно, помогает с проблемой класса. Теперь менеджер GRID правильно размещает текстовый виджет внутри среднего фрейма self.f2, однако, даже когда я устанавливаю прикрепление в myText.grid(sticky = N+S+E+W), он не расширяется правильно. Так я подумал следующее:

1) Установив изменение размера корневого окна с помощью конструктора def __init__ class App, я установил его так, чтобы первая строка и нулевой столбец окна приложения получали все пространство, выделенное для изменения размера в self.rowconfigure( 1, weight = 1) и self.columnconfigure( 0, weight = 1).

2) Теперь, когда рамка self.f2 помещена в строку 1, она получит все изменения размера с self.f2.grid(N+S+E+W).

3) Теперь я заполняю этот настраиваемый фрейм виджетом text(), который настроен на ВСЕ пространство в этом фрейме, указав self.myText.grid( sticky = N+S+E+W).

Но виджет text() не заполняется self.f2! Когда я обычно делаю это без специального класса, использование атрибута sticky = N+S+E+W работает правильно. Я правильно об этом думаю?


person voxeloctree    schedule 20.10.2011    source источник


Ответы (1)


Frame.__init__ необходимо передать родительскому элементу:

class myTestFrame( tk.Frame ):
    tk.Frame.__init__(self, parent, *args, **kwargs)

Запускаемый пример:

import sys
import Tkinter as tk
E=tk.E
W=tk.W
N=tk.N
S=tk.S
def main():
    app = App()
    app.master.title("Sample application")
    app.mainloop()

class App(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.grid(sticky=N+S+E+W)

        top = self.winfo_toplevel()
        top.rowconfigure(0, weight=1)
        top.columnconfigure(0, weight=1)

        self.rowconfigure(1, weight=1)
        self.columnconfigure(0, weight=1)
        self.__createWidgets()

    def __createWidgets(self):
        self.f1 = tk.Frame(self, height=100, width=200, bg='green')
        self.f1.grid(row=0, sticky=E+W)

        self.f2 = myTestFrame(self, bg='yellow', height=100, width=200)

        self.f3 = tk.Frame( self, bg = "cyan", height = 100, width = 200)
        self.f3.grid(row=2, sticky=E+W)

        self.quitButton = tk.Button(self, text="Quit", command=self.quit)
        self.quitButton.grid(row=4, column=0, sticky=E+W)

class myTestFrame( tk.Frame ):
    def __init__(self, parent, cnf={}, **kw):
        tk.Frame.__init__(self, parent, cnf, **kw)
        self.grid(row=1, sticky=N+S+E+W)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)                
        self.myText = tk.Text(self)
        self.myText.grid(row=0, sticky=N+S+E+W)

if __name__ == "__main__":
    main()
person unutbu    schedule 20.10.2011
comment
Большое тебе спасибо. Все, что мне нужно было сделать, это изменить Frame .__ init __ (self, None) на Frame .__ init __ (self, parent). Спасибо еще раз. - person voxeloctree; 20.10.2011
comment
Я скоро поговорил. См. Редактирование выше. Я очень хочу понять, что здесь происходит. - person voxeloctree; 21.10.2011
comment
myTestFrame необходимо вызвать rowconfigure и columnconfigure, чтобы установить weight=1. В противном случае виджеты в его сетке не расширяются. Я узнал об этом здесь. - person unutbu; 21.10.2011
comment
Спасибо еще раз. Отличный ресурс. - person voxeloctree; 22.10.2011