【PyQt5 GUI実践】気象データ可視化アプリを作ろう!(3) データ取得とグラフ描画ロジックの統合 🔗

「GUIのボタンを押したら、Pythonのデータ処理関数を動かしたい!」
「Webから取得したデータを、どうやってアプリの画面に反映させるの?」
「これまで作ってきた部品を全部つなぎ合わせて、ついにアプリを完成させたい!」

こんにちは! PyQt5探検隊、隊長のPythonistaです! 第1回ではウィンドウとレイアウトの骨格を、第2回ではインタラクティブな地図をアプリに埋め込み、PythonとJavaScriptを連携させる核心部分を実装しましたね。アプリの「見た目」と「入力」の部分が完成しました。

シリーズ第3回となる今回は、いよいよ最終組み立て工程です!これまでに作成したGUIの部品と、以前のプロジェクトで作成した**データ取得・分析・可視化のロジック(頭脳)**を完全に統合し、気象データ可視化アプリケーションを完成させます。ユーザーの操作(ボタンクリック)をきっかけに、一連のデータ処理が走り、結果がグラフとして表示される…そんな、本格的なアプリケーションの挙動を、あなたの手で実現させましょう!


1. 準備:これまでのコードと最終的な目標

今回は、以下の2つの要素を統合します。

  1. GUIの骨格(第1回・第2回で作成): PyQt5で作成したウィンドウ、コントロールパネル、地図表示エリア。
  2. データ処理ロジック: 以前のプロジェクトで作成した、Open-Meteo APIから気象データを取得し、Pandasで集計し、Matplotlibでグラフを描画する関数群。

最終的な目標は、「データ取得 & グラフ表示」ボタンをクリックすると、コントロールパネルで指定された地点と期間の気象データが取得・処理され、Matplotlibのグラフウィンドウがポップアップ表示される、という一連の流れを完成させることです。


2. ステップ1:データ処理関数をGUIクラスに統合する

まずは、以前作成したデータ取得・可視化の関数群を、私たちのWeatherAppクラスのメソッドとして取り込めるように、少しだけ修正を加えます。これにより、GUIの各要素(緯度経度や日付など)から値を受け取って、動的に処理できるようになります。

2.1. GUI用に修正したデータ処理関数

(この部分は、以前のスクリプトから関数をコピーし、GUIの変数を受け取れるように引数を調整したものであることを説明します。)

# --- データ処理関数(GUI用に修正) ---
def get_weather_data(lat, lon, start_date_str, end_date_str):
    # ... (ユーザー提供のコード。APIからデータを取得し、DataFrameを返す) ...
    print(f"気象データの取得を開始します... ({start_date_str} ~ {end_date_str})")
    # (中略)
    weather_df = pd.DataFrame({
        "date": date_range,
        "temperature_mean": daily_temperature_2m_mean,
        "humidity_mean": daily_relative_humidity_2m_mean,
        "wind_speed_ms": wind_speed_ms
    })
    return weather_df

def plot_weather_data(df, start_date_str, end_date_str, location_name):
    # ... (ユーザー提供のコード。DataFrameからグラフを描画する) ...
    print("データの分析とグラフ作成を開始します...")
    # (中略)
    plt.show()

これらの関数を、WeatherAppクラスが定義されている.pyファイルの上部(または別のファイルからインポートする形)に配置します。


3. ステップ2:ボタンクリックイベントと処理関数を紐付ける

いよいよ、GUIの操作とデータ処理ロジックを接続します。これは、ボタンの「クリックされた」というシグナルに、実行したい関数(スロット)を接続することで実現します。

3.1. ボタンクリックで呼び出されるメソッドの作成

WeatherAppクラスの中に、ボタンがクリックされたときに実行されるメインの処理メソッドrun_analysisを作成します。このメソッドが、UIから情報を収集し、データ処理関数を呼び出し、UIの状態を更新するという、司令塔の役割を果たします。

# WeatherAppクラス内に、以下のメソッドを追加します。

def run_analysis(self):
    # 1. GUIのウィジェットから現在の設定値を取得
    start_date = self.start_date_edit.date().toString("yyyy-MM-dd")
    end_date = self.end_date_edit.date().toString("yyyy-MM-dd")
    
    # 2. 処理中であることをユーザーに通知 (UIの更新)
    self.statusBar().showMessage("データを取得・処理中です...", 0) # 0はタイムアウトなし
    self.fetch_button.setEnabled(False) # ボタンを一時的に無効化
    QApplication.processEvents() # UIの表示を即座に更新するためのおまじない

    # 3. データ取得関数を呼び出す
    df = get_weather_data(self.lat, self.lon, start_date, end_date)

    # 4. 取得したデータをCSVに保存
    if df is not None and not df.empty:
        start_f = self.start_date_edit.date().toString("yyyyMMdd")
        end_f = self.end_date_edit.date().toString("yyyyMMdd")
        safe_location_name = "".join(c for c in self.location_name if c.isalnum())
        filename = f"{start_f}_{end_f}_{safe_location_name}.csv"
        df.to_csv(filename, index=False)
        self.statusBar().showMessage(f"'{filename}'に保存しました。グラフをプロットします...", 0)
        
        # 5. グラフ描画関数を呼び出す
        plot_weather_data(df, start_date, end_date, self.location_name)
        self.statusBar().showMessage("完了しました。", 5000) # 5秒後にメッセージを消す
    else:
        self.statusBar().showMessage("有効なデータが取得できませんでした。", 5000)
        
    # 6. ボタンを再度有効化
    self.fetch_button.setEnabled(True)

3.2. ボタンのclickedシグナルとrun_analysisメソッドを接続

最後に、create_widgets(またはinitUI)メソッドの中で、ボタンを作成している部分に以下の1行を追加(またはコメントアウトを解除)するだけです。

# create_widgets (または initUI) メソッドの中
self.fetch_button = QPushButton("データ取得 & グラフ表示")
# ボタンがクリックされたら、self.run_analysisメソッドを呼び出すように接続
self.fetch_button.clicked.connect(self.run_analysis)
controls_layout.addWidget(self.fetch_button)

これで、ユーザーがボタンをクリックするとrun_analysisメソッドが実行され、一連のデータ処理が走り、最終的にグラフが表示されるという、アプリケーションの主要な機能が完成しました!


4. 完成したアプリケーションの動作確認

全てのコードを統合した最終的なスクリプトを実行してみましょう。

  1. アプリケーションが起動します。
  2. 右側の地図をクリックして、好きな地点を選択します。左側の地点情報が更新されることを確認します。
  3. 左側のカレンダーで、分析したい期間(開始日と終了日)を指定します。
  4. 「データ取得 & グラフ表示」ボタンをクリックします。
  5. ステータスバーに「データを取得・処理中です...」と表示され、ボタンが一時的に押せなくなります。
  6. しばらくすると、Matplotlibのグラフウィンドウがポップアップ表示され、ステータスバーに「完了しました。」と表示されます。
  7. スクリプトと同じディレクトリに、(開始日)_(終了日)_(地名).csvという名前で気象データが保存されていることも確認できます。

5. まとめと【オプション】次なるステップへの挑戦

おめでとうございます!これで、PyQt5を使った本格的なGUIアプリケーションが完成しました! このプロジェクトを通して、私たちは以下の重要なステップを経験しました。

  • PyQt5のレイアウトマネージャを使い、複雑なUIの骨格を設計・実装しました。
  • QWebEngineViewQWebChannelを使い、デスクトップアプリにインタラクティブなWebコンテンツ(地図)を埋め込み、PythonとJavaScriptを連携させました。
  • GUIのイベント(ボタンクリック)をトリガーにして、データ取得・処理・可視化という一連のバックエンドロジックを実行させ、その結果をユーザーにフィードバックしました。

これは、単なるスクリプトから、誰でも使える「アプリケーション」へと大きな飛躍です。この経験は、あなたのプログラミングスキルと自信を大きく向上させたことでしょう。

さて、このアプリは完成しましたが、冒険はまだ終わりません。
「このアプリを、Pythonがインストールされていない友達のPCでも動かせるようにしたい!」と思いませんか?

もしご興味があれば、次回の【オプション編】では、このアプリケーションをPyInstallerというツールを使って、Windowsなら.exeファイル、macOSなら.appファイルといった、誰でもダブルクリックで実行できる単一のファイルにパッケージングする方法に挑戦してみたいと思います。あなたの作ったアプリを、世界中の人に届けるための最後のステップです。お楽しみに!

その他の投稿はこちら

コメント

このブログの人気の投稿

タイトルまとめ

これで迷わない!WindowsでPython環境構築する一番やさしい方法 #0

【Python標準ライブラリ完結!】11の冒険をありがとう!君のPython力が飛躍する「次の一歩」とは? 🚀