Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
253 views
in Technique[技术] by (71.8m points)

python - Tkinter Canvas create_window()

I'm trying to use Tkinter Canvas (self._canvas) to create window using create_window function. The window field for that function is a Tkinter Frame (self._tableFrame). Can someone please help me out on how to make self._tableFrame to expand to size of self._canvas automatically (Even after the window size changed by user)?

Code:

from Tkinter import Scrollbar as tkScrollBar
from Tkinter import Frame as tkFrame
from Tkinter import Canvas as tkCanvas
from Tkinter import Entry as tkEntry
from Tkinter import StringVar as tkStringVar
from Tkinter import Tk, HORIZONTAL, N, S, E, W, RIGHT, LEFT, BOTTOM, X, Y, BOTH
from Tkinter import TOP


class Widget(tkFrame):
    def __init__(self, master=None):
        tkFrame.__init__(self, master)

        self._str    = tkStringVar()
        self._widget = tkEntry(self)

        self._widget.config(textvariable=self._str, borderwidth=1, width=0)
        self._widget.pack(expand=True, fill=X)

    def settext(self, str_):
        self._str.set(str_)

    def gettext(self):
        return self._str.get()


class Application(tkFrame):
    def __init__(self, rows, cols, master=None):
        tkFrame.__init__(self, master)

        yScroll = tkScrollBar(self)
        xScroll = tkScrollBar(self, orient=HORIZONTAL)

        self._canvas = tkCanvas(self,
                yscrollcommand=yScroll.set, xscrollcommand=xScroll.set)
        yScroll.config(command=self._canvas.yview)
        xScroll.config(command=self._canvas.xview)

        self._table      = [[0 for x in range(rows)] for x in range(cols)]
        self._tableFrame = tkFrame(self._canvas)

        for col in range(cols):
            self._tableFrame.grid_columnconfigure(col, weight=1)
            for row in range(rows):
                self._table[row][col] = Widget(master=self._tableFrame)
                self._table[row][col].settext("(%d, %d)" % (row, col))
                self._table[row][col].grid(row=row, column=col, sticky=E+W)

        # For debugging
        self._canvas.config(background="blue")
        self._tableFrame.config(background="red")

        yScroll.pack(side=RIGHT, fill=Y)
        xScroll.pack(side=BOTTOM, fill=X)

        self._canvas.create_window(0, 0, window=self._tableFrame, anchor=N+W)
        self._canvas.pack(side=LEFT, fill=BOTH, expand=True)


tkRoot  = Tk()

# Application Size and Center the Application
appSize = (800, 600)
w       = tkRoot.winfo_screenwidth()
h       = tkRoot.winfo_screenheight()

x = w / 2 - appSize[0] / 2
y = h / 2 - appSize[1] / 2
tkRoot.geometry("%dx%d+%d+%d" % (appSize + (x, y)))
tkRoot.update_idletasks() # Force geometry update

app = Application(5, 5, master=tkRoot)
app.pack(side=TOP, fill=BOTH, expand=True)
tkRoot.mainloop()
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can bind self._canvas with the event <Configure>, and then call itemconfig with the id of the frame added to the canvas (not directly the reference to the widget):

def __init__(self, rows, cols, master=None):
    # ...
    self._frame_id = self._canvas.create_window(0, 0, window=self._tableFrame, anchor=N+W)
    self._canvas.pack(side=LEFT, fill=BOTH, expand=True)
    self._canvas.bind("<Configure>", self.resize_frame)

def resize_frame(self, e):
    self._canvas.itemconfig(self._frame_id, height=e.height, width=e.width)

By the way, I recommend you to rewrite your import statements, which in my opinion are quite repetitive and unpythonic:

import Tkinter as tk
# Use tk.Tk, tk.Canvas, etc.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...