6

たとえば、ウィンドウをラベルで埋めたいのですが、列が現在のウィンドウ(または親フレーム)のサイズよりも大きくなったときにラベルを折り返したいと思います。

レイアウトを使用してみましたgridが、次の行に次の要素を配置するタイミングを知るために、各行のコンテンツのサイズを自分で計算する必要があります。

私が尋ねる理由は、ある種のタイルファイルアイコンを作成したいからです。

または別の質問をすると、FlowLayoutTkInter用のSwingのようなものはありますか?

4

2 に答える 2

8

このようなものが必要なときに行うのは、コンテナのテキストウィジェットを使用することです。テキストウィジェットにはウィジェットを埋め込むことができ、テキストと同じように折り返されます。ウィジェットがすべて同じ高さである限り、効果はかなり素晴らしいです。

例(著者の要求に応じて質問から切り取って貼り付けます):

textwidget = tk.Text(master)
textwidget.pack(side=tk.LEFT, fill=tk.BOTH)
for f in os.listdir('/tmp'):
    textwidget.window_create(tk.INSERT, window=tk.Label(textwidget, text=f))
于 2012-10-25T20:35:05.337 に答える
1

フレーム内でフロー動作を行う方法は次のとおりです。

これを行う関数を作成しました。基本的に、フレームを関数(ルートまたはトップレベルではない)に渡すと、関数はフレームのすべての子を調べ、それらを調べてサイズを測定し、フレームに配置します。

配置手順は次のとおりです
  • 最初のウィジェットを配置し、その幅に等しい量だけxを移動します。
  • 次のウィジェットを測定します。
  • 次のウィジェットを配置するとフレーム幅を超える場合は、そのx値を0に上げ、現在の行の最大のウィジェットに等しい値に下げます(新しい行を開始します)。
  • 新しい行を開始しているので、最大のウィジェットの値をリセットします。
  • すべてのウィジェットが配置されるまで繰り返します。
そのプロシージャをフレームイベントのサイズ変更にバインドします。
私はこれを機能させるために3つの関数を使用しました:
  1. プロシージャを実行する関数。
  2. フレームのサイズ変更を関数にバインドする関数。
  3. フレームのサイズ変更を解除する機能。

関数は次のとおりです。

from tkinter import *


def _reorganizeWidgetsWithPlace(frame):
    widgetsFrame = frame
    widgetDictionary = widgetsFrame.children
    widgetKeys = []  # keys in key value pairs of the childwidgets

    for key in widgetDictionary:
        widgetKeys.append(key)

    # initialization/priming loop
    width = 0
    i = 0
    x = 0
    y = 0
    height = 0
    maxheight = 0
    # loop/algorithm for sorting
    while i < len(widgetDictionary):
        height = widgetDictionary[widgetKeys[i]].winfo_height()
        if height > maxheight:
            maxheight = height

        width = width + widgetDictionary[widgetKeys[i]].winfo_width()

        # always place first widget at 0,0
        if i == 0:
            x = 0
            y = 0
            width = widgetDictionary[widgetKeys[i]].winfo_width()

        # if after adding width, this exceeds the frame width, bump
        # widget down.  Use maximimum height so far to bump down
        # set x at 0 and start over with new row, reset maxheight
        elif width > widgetsFrame.winfo_width():
            y = y + maxheight
            x = 0
            width = widgetDictionary[widgetKeys[i]].winfo_width()
            maxheight = height

        # if after adding width, the widget row length does not exceed
        # frame with, add the widget at the start of last widget's
        # x value

        else:
            x = width-widgetDictionary[widgetKeys[i]].winfo_width()

        # place the widget at the determined x value
        widgetDictionary[widgetKeys[i]].place(x=x, y=y)
        i += 1
    widgetsFrame.update()


def organizeWidgetsWithPlace(frame):
    _reorganizeWidgetsWithPlace(frame)
    frame.bind("<Configure>", lambda event: _reorganizeWidgetsWithPlace(frame))
    _reorganizeWidgetsWithPlace(frame)


def stopOrganizingWidgetsWithPlace(frame):
    frame.unbind("<Configure>")

そして、これが使用中のそれらの例です:

def main():
    root = Tk()
    root.geometry("250x250")
    myframe = Frame(root)
    # make sure frame expands to fill parent window
    myframe.pack(fill="both", expand=1)

    buttonOrganize = Button(myframe, text='start organizing',
                            command=lambda: organizeWidgetsWithPlace(myframe))
    buttonOrganize.pack()

    buttonStopOrganize = Button(myframe, text='stop organizing',
                                command=lambda: stopOrganizingWidgetsWithPlace(myframe))
    buttonStopOrganize.pack()

    ##### a bunch of widgets #####
    button = Button(myframe, text="---a random Button---")
    canvas = Canvas(myframe, width=80, height=20, bg="orange")
    checkbutton = Checkbutton(myframe, text="---checkbutton----")
    entry = Entry(myframe, text="entry")
    label = Label(myframe, text="Label", height=4, width=20)
    listbox = Listbox(myframe, height=3, width=20)
    message = Message(myframe, text="hello from Message")
    radioButton = Radiobutton(myframe, text="radio button")
    scale_widget = Scale(myframe, from_=0, to=100, orient=HORIZONTAL)
    scrollbar = Scrollbar(myframe)
    textbox = Text(myframe, width=3, height=2)
    textbox.insert(END, "Text Widget")
    spinbox = Spinbox(myframe, from_=0, to=10)

    root.mainloop()

main()
知らせ:

それらをグリッド化、パック、または配置する必要がないこと。フレームを指定する限り、関数が呼び出されたときにすべてが一度に実行されます。とても便利です。また、ウィジェットをグリッド化してから別のウィジェットをパックしてから別のウィジェットを配置しようとすると、1つのジオメトリマネージャーしか使用できないというエラーが発生するため、煩わしい場合があります。これは単に前の選択肢を上書きして配置するだけだと思います。この機能をドロップするだけで、管理が引き継がれると思います。これまでのところ、これは常にうまくいきましたが、ジオメトリマネージャーを組み合わせて使用​​することは絶対に避けてください。

最初はボタンがパックされていますが、ボタンを押した後、ボタンが配置されていることに注意してください。

グリッドマネージャーと非常によく似た機能を実行する同様の関数セットがあるため、関数に「WithPlace」という名前を付けました。

于 2021-07-26T14:13:03.897 に答える