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

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

ただいまの
回答率

87.79%

Python GUI Tkinterでの戻り値

解決済

回答 1

投稿

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

score 27

お世話になっております。
PythonのTkinterのGUIから読込みたいファイルのパスを取得したいのですが戻り値がNoneとなり、パスが取得できません。

 ディレクトリ

main.py
read_file.py
sample.xlsx
templates
|-index.html

main.py

# -*- coding: utf-8 -*-
from flask import Flask, render_template
import os
import read_file as rf
import tkinter
from tkinter import ttk, filedialog, messagebox

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def index():
    f = rf.draw_GUI()
    print(f) #Noneになる
    return render_template('index.html')

if __name__ == '__main__':
    port = int(os.getenv('PORT', 5000))
    app.run(host='0.0.0.0', port=port, threaded=True, debug=True)

read_file.py

import tkinter
from tkinter import ttk, filedialog, messagebox

def draw_GUI():
    tk = tkinter.Tk()
    tk.geometry('500x500')
    tk.title('Select input File')

    def ask_file():
        path = filedialog.askopenfilename()
        file_path.set(path)

    def submit():
        input_dir = file_path.get()
        return input_dir

    file_path = tkinter.StringVar()

    frm = ttk.Frame(tk)
    frm.grid(column=0, row=0, sticky=tkinter.NSEW, padx=5, pady=10)

    filepath_label = ttk.Label(frm, text='ファイル指定')
    filepath_box = ttk.Entry(frm, textvariable=file_path)
    filepath_btn = ttk.Button(frm, text='参照', command=ask_file)
    submit_btn = ttk.Button(frm, text='実行', command=submit)

    filepath_label.grid(column=0, row=0, pady=10)
    filepath_box.grid(column=1, row=0, sticky=tkinter.EW, padx=5)
    filepath_btn.grid(column=2, row=0)
    submit_btn.grid(column=1, row=1)

    tk.columnconfigure(0, weight=1)
    tk.rowconfigure(0, weight=1)
    frm.columnconfigure(1, weight=1)

    tk.mainloop()

http://localhost:5000/にアクセスすると添付のような画面になり参照ボタンを押すと選択したファイルのパスがテキストボックスに入力されるのですが、実行ボタンを押した時に変数に入れる事が出来ない状態です。
実行ボタンを押した時に変数にファイルのパスを取得して、tkinterを終了したいのですがどこを修正したら良いか教えて頂けませんでしょうか。

宜しくお願い致します。

イメージ説明

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

コードの問題点は、return が無い為です。

mainloop 後に tkinter の情報にアクセスするのは少し工夫が必要で、
一旦別の変数にいれてから quit で mainloop を終了します

    input_dir = ""
    def submit():
        nonlocal input_dir
        input_dir = file_path.get()

        tk.quit() # mainloop を終了する

        # XXX: ここでのreturn は mainloop() 内で処理される

   # draw_GUI 関数内 mainloop 後に

   return input_dir

但し、他に問題があって、こちらの方が重要
Web でのリクエスト処理内で GUI (tkinter等) を使うべきではありません。

設計上の重大な問題があります。

  • このスクリプトのGUIは「サーバー側」で実行されます。
    ローカル環境でサーバーを動かす場合は、
    実質クライアントとサーバーが同じ環境ですが、
    他人がアクセスする場合や、外部でサーバーを動かす場合を想定できてません。

このサーバーを外部公開した場合、
リクエストの度にサーバー側でダイアログが開く事になります。
サーバー利用するような環境では、デスクトップ環境は構築されてない事の方が多いはず。
 

  • Web のリクエスト処理内での GUI は、
    GUI のイベントループがリクエスト処理を一時的にブロックするので、
    サーバーのパフォーマンス低下につながります。

許容できるとすれば、外部公開をせず自分しか使わないような状況ですが、
その場合でも設計の見直しをお勧めします。

解決策:
ブラウザ(クライアント)側で処理できるように HTML でファイル入力欄を作ってください。

ローカル環境で動く GUI (tkinter) 内で処理したい場合でも、
サーバーとは必要なデータのみを通信をするような構成にした方が良いです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2021/03/03 09:03

    teamikl様
    ご回答ありがとうございます。
    頂いたコードを試したところ戻り値を取得できました。

    設計については少し考えなおしてみます。
    ご指摘頂きありがとうございました!

    キャンセル

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

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

関連した質問

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