tkinterでボタンとメニューに同じ関数を割り当てる。

 tkinterでGUIアプリを作っていて、Menubarがあるのでそこにメニューを追加、画面上にボタンも付けて、ボタンを押してもメニューから選んでも同じ処理をしたい、となったんだけれど、ボタンの方は動くのに、メニューの方からは「引数が足りません!」と怒られました。

怒られたコードはざっくりこんな感じ。

    # メニューバー
    menubar = tk.Menu(root, tearoff=False)
    root["menu"] = menubar
    filemenu = tk.Menu(menubar, tearoff=False)
    menubar.add_cascade(label="File", menu=filemenu, accelerator="F")
    filemenu.add_command(label="開く", command=self.open_pyfile)
    
    # ボタン
    self.btn1_text = tk.StringVar()
    self.btn1_text.set(gui_text["button1"])
    button1 = ttk.Button(frame1, textvariable=self.btn1_text, style="TButton")
    button1.bind("<ButtonPress>", self.open_pyfile)

def open_pyfile(self, event):
    """ファイルを開く

    Args:
        event (_type_): _description_

    Returns:
        Path: 選択されたファイル
    """
    ofile = filedialog.askopenfilename(
        initialdir=Path.cwd(),
        title="ファイルを開く",
        filetypes=(
            ("Python files", "*.py;*.pyw"),
            ("JSON files", "*.json"),
            ("All files", "*.*"),
        ),
    )

    self.file1.set(ofile)
    return Path(ofile)
ボタンの方はちゃんと動くけれど、メニューから「開く」を選んだ瞬間に引数が足りないと言われます。 ググってみても検索語の選び方がうまくないのか、lambda: するといいよ、とかいろいろ引っかかるんですが、こうすれば解決できました。
def open_pyfile(self, event=None):
要は、eventが引き数にあればそれでいいし、ない場合にはNoneにしちゃえ、ということです。実際にevent変数を使用した処理をしているなら、event==Noneならメニューから呼ばれたものとして扱えばいいわけですし。

自分的には目からウロコでした。

0 件のコメント:

コメントを投稿

ArchLinux on WSLでどたばた。

Windows11のノートPCで、WSLでArchLinuxをインストールしようと思ってちょっと引っかかったところがあったのでメモ。 インストール自体はArchWSLのページの通りで進みましたが、pacman -Syu するとtrusted keyが云々でできませんでした。 そこ...