質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • Python 3.x

    6418questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • canvas

    259questions

    HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

  • Tkinter

    149questions

    Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python3 Tk ウィジェットの配置について

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 947

IOError

score 12

Python3 の Tk を使ってあるウィンドウを作りたいと思います。

○目標
・ウィンドウは左,右上,右下(順に win1, win2, win3 と呼ぶ)の3つの構成
・win1 は、番号の書いたリストボックスで上下に関してウィンドウのリサイズに対応
・win2 は、Canvasで縦の長さは固定、横幅はウィンドウのリサイズに対応
・win3 は、Canvasで上下左右ともにウィンドウのリサイズに対応

現時点で書いたコードを記載します。

from tkinter import *

def a(event):
    canvas2.scan_mark(event.x, event.y)

def b(event):
    canvas2.scan_dragto(event.x, event.y, gain=1)

if __name__ == '__main__':
    w, h = 200, 200        # ウィンドウサイズ
    r = 20                # 円の半径

    root = Tk()
    pw = PanedWindow(root, sashwidth = 10, orient = HORIZONTAL)

    # ウィンドウ左側のリストボックス
    listbox = Listbox(pw)
    for i in range(50):
        listbox.insert(END, i+1)
    pw.add(listbox)

    # ウィンドウ右側のスクロール可能Canvas
    frame = Frame(root)
    canvas = Canvas(frame, width = w, height = 30, bg = "#aaaaaa")
    canvas2 = Canvas(frame, width = w, height = h, bg = "#cccccc", scrollregion=(0, 0, w*2, h*2))


    # キャンバス描画
    oval = canvas2.create_oval(w-r, h-r, w+r, h+r)

    canvas2.bind("<ButtonPress-1>",a)
    canvas2.bind("<B1-Motion>",b)


    # ウィジェットの配置
    canvas.grid(row=0, column=0, sticky=E+W)
    # スクロールバーの配置
    xscroll = Scrollbar(frame, orient=HORIZONTAL, command=canvas2.xview)
    xscroll.grid(row=3, column=0, sticky=E+W)
    yscroll = Scrollbar(frame, orient=VERTICAL, command=canvas2.yview)
    yscroll.grid(row=2, column=1, sticky=N+S)

    canvas2.config(xscrollcommand=xscroll.set, yscrollcommand=yscroll.set)
    canvas2.grid(row=2, column=0, sticky=N+E+W+S)

    frame.grid_rowconfigure(0, weight=1)
    frame.grid_columnconfigure(0, weight=1)
    frame.grid(sticky=N+E+W+S)

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

    pw.add(frame)
    pw.pack(expand = True, fill = BOTH)

    root.mainloop()

上記のコードの問題点は、「ウィンドウのリサイズによって、win2 の位置が移動してしまい上下に余白ができてしまう」ことです。この部分を、「ウィンドウがリサイズされても win2 の位置は右上固定とし、win3 がリサイズされて余白ができない」というように改善したいと思います。

また、win2 右側が win3 のスクロールバーに合わせて、画面の右端まで届いていない状況です。これを win2 の幅と、win3 のスクロールバーまで含めた幅が一致するようにしたいです。
この点は追加ですので、可能であればアドバイスください。

わかる方がいらっしゃいましたらご教授ください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

求めてる挙動になってるかどうか怪しいですが、なんとなくできたので共有します。全文は長いのでgistにしました。

https://gist.github.com/tell-k/36d76665b866faf7c84c4993055ff0ec

ポイントは2点です。

61行目付近で rowconfigure を追加しました。そのとき一番上の行は weight=0 にしています。 weight=0 にすることでリサイズの影響を受けなくなり、上下に余白ができなくなります。

    # rowconfigureで一行目を固定
    frame.grid_rowconfigure(0, weight=0)
    frame.grid_rowconfigure(1, weight=1)

10行目付近で、 ResizeCanvas(Canvas) を作って、それを canvas2 に設定しています。 ウィンドウのリサイズが発生するたびに、canvas2 の高さを自動的に調節してくれます。

class ResizeCanvas(Canvas):

    def __init__(self, *args,**kwargs):
        super().__init__(*args, **kwargs)
        self.frame = args[0]
        self.bind("<Configure>", self.on_resize)

    def on_resize(self,event):
        # 右下のCanvasをリサイズに合わせて高さを自動調整
        self.height = self.frame.winfo_height() - 30 # 30 == canvas.height
        self.config(height=self.height)

参考

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/28 13:09

    tell_k さん、ありがとうございました。
    まさにやりたかったことが実装されていました。
    rowconfigure で欄を分けてしまえばよかったんですね。
    また、ResizeCanvasクラスの init メソッドは初めて見る文法で、詳しい使い方がわからないので、これから勉強していこうと思います。

    ご丁寧にリンクまで用意していただき、ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    6418questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • canvas

    259questions

    HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

  • Tkinter

    149questions

    Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。