tkinter がうまくいかないので、PyQt6でWidget（ウィジェット）に挑戦（その４）自作programをRadiButtonでリスト化


# 環境
>・MacOS Ventura 13.2
・python3.10.4
・pyqt6(インストールが必要です。% python3 -m pip install pyqt6)

# 作った理由
>programを色々と作って行くといっぱいたまりますよね。そう言う時ディレクトリにある自作programをRadiButtonでリスト化して、ラジオボタンを選択するだけで実行できれば楽ちんだなと考えました。ターミナルもprogramごとに開かないで、一度ひらけばOKです。

# 出来上がったWedget
**"フォルダーに新規ターミナル"**　をクリック

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/594b5d0b-b4c7-e9b4-4e06-0680dd118ba1.png" alt="スクリーンショット" width="300">

ターミナルがひらいたら　**% python3 main.py** で実行
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/19a3a424-ecd0-40aa-ee9d-0a1b06ba2694.png" alt="スクリーンショット" width="300">


**ラジオボタンを選択してSelectをクリック**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/ed677fdd-e235-d2fb-2941-61a637cb21a6.png" alt="スクリーンショット" width="300">

**選択したディレクトリのプログラムが実行されて、Widgetが表示される。**
Closeをクリックするまで、選択は繰り返し行えます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/70fe03ee-a2ee-448f-9e09-34d0ced8276d.png" alt="スクリーンショット" width="300">

これだけのことですが、一度terminalを開き、main.pyを実行するだけで、
**<font color="red">terminalをprogram毎に開かない</fo0nt>** で実行できます。
楽ちんです。

# 事前準備
>1、**python ファイルのあるディレクトリが必要です。**(ディレクトリの出来上がりのイメージを参照してください。)
この中のディレクトリをリストにして、RadioButtonにします。
　なお、表示するリストから**外したいディレクトリ**もあると思います。外す場合は、_(アンダーバー)を対象のディレクトリの頭部につけてください。
　（頭部にアンダーバー( _ )の付いている_test_1及び_test_2のディレクトリについては、RadioButtonの表示から**省かれることを確認するダミー**です。確認後削除しても構いません）


>2、**01_ から03_まではプログラムの入っているディレクトリです。**
RadioButoonで」実行したい番号を選択した時に、キーとしている名称はメインプログラムの名称が"main.py"となっているものとしています。

```python
           # 実行
            sb.run(['python3', 'main.py'])
```
><font color='red'>'main.py'</font>を普段使っている名称に変更する場合は、全ての対象ディレクトリで共通の名称にして下さい。
sb.run(['python3', 'xxxx.py'])の'xxxx.py'部分の変更も忘れずに！



### (ディレクトリの出来上がりのイメージ)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/426983e1-4466-8a99-2ace-391d4df1e189.png" alt="スクリーンショット" width="250">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/f2b2fe18-46b2-a9c5-944d-e6854469b8ac.png" alt="スクリーンショット" width="250">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/903a1995-5ca4-8232-0f33-ee3f50f21878.png" alt="スクリーンショット" width="250">

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/796a6e63-08a0-699f-44a4-063898cfd5a2.png" alt="スクリーンショット" width="250">

>3、**programの最初にPATHを記述する箇所があります。**
このprogram(main.py)を置いた直前のディレクトリのフルパスを記述してください


 Finderの下部に表示されている「”xxxxx”のパス名をコピー」を右クリックしてコピーを取得し、貼り付けて下さい。（ご存じと思いますが念のため）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/7c06ae09-62f2-b7ce-9a8c-7c2b5c76d1b8.png" alt="スクリーンショット" width="300">

4、**実行ファイルは、リスト化したいディレクトリと同じ場所にに保管してください。**(ディレクトリの出来上がりのイメージを参照してください。)
実行は、<font color='red'>% python3 main.py</font>とTerminalで記述して下さい。一度実行すれば、terminalは隠しておいても大丈夫です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/a178b704-5a42-e62b-c58e-8cc8b292050c.png" alt="スクリーンショット" width="300">

# それでは下記のCodeをコピペして試して見てください＞
```python
# 一つのディレクトリにあるいくつかのファイルから、一つのpython faileを選択して実行する

# ラジオボタンにつける名称をディレクトリからリストを作り、そのリストから付ける
# ラジオボタンをチェックし、buttonをクリックするとその番号を返す
# 選択された番号からpython3 Fileを選択してmain.pyを実行する

# ---------------------------------------------
import pandas as pd
import os
import subprocess as sb
# ---------------------------------------------
# ディレクトリ名のみの一覧を取得・実行するディレクトリに移動で使用
# 本programのあるディレクトリのフルパス
path = '/Users/あなたの名前/Library/Mobile Documents/com~apple~CloudDocs/03_qiita関係/Qiita投稿Program/15_tkinter がうまくいかないので、PyQt6でWidget（ウィジェット）に挑戦（その４）'
# ---------------------------------------------
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QRadioButton, QPushButton, QLabel
from PyQt6.QtGui import QFont   # フォントのサイズを設定
# ---------------------------------------------

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()
    # -----------------------------------------
    def initUI(self):
        '''画面タイトルの設定'''
        self.setWindowTitle('Select Meni')

        # -------------------------------------
        '''mainレイアウトの設定'''
        layout = QVBoxLayout()
        self.setLayout(layout)

        # -------------------------------------
        '''widgetの用意'''
        # ---------------
        #rdiobuttonの準備（リストから設定）
        # ディレクトリ名のみの一覧を取得
        files = os.listdir(path)
        files_dir = [f for f in files if os.path.isdir(os.path.join(path, f))]

        # --------------------------------------
        #「files_dir」リストから先頭がアンダースコアで始まるファイルを除外する
        files_dir = [file for file in files_dir if not file.startswith('_')]

        # --------------------------------------
        # 作成したリストのディレクトリ名をラジオボタンの名称に設定
        self.radiobuttons = []

        font = QFont()# フォントのサイズを設定
        font.setPointSize(15)  # フォントのサイズを設定
        files_dir.sort()  # リストを番号順に並び替える
        
        for i, option in enumerate(files_dir,start = 1):# start=1で開始値指定
            rb = QRadioButton(option)
            rb.setObjectName(str(i))
            rb.setFont(font)  # フォントを設定
            layout.addWidget(rb)
        
            self.radiobuttons.append(rb)
            # -------------------
            # 選択漏れ防止(1番目にチェックが入る)
            if i == 1:
                rb.setChecked(True)
            else:
                pass
            # -------------------

        self.mylist = files_dir

        # -------------------
        # buttonの作成
        self.button = QPushButton('Select')
        self.button.setFont(font)  # フォントを設定
        self.button.clicked.connect(self.show_selected)
        layout.addWidget(self.button)

        # -------------------
        # 計算結果を表示するためのラベルの用意
        self.result_label = QLabel('選択結果を表示',self)
        self.result_label.setFont(font)  # フォントを設定
        layout.addWidget(self.result_label)
        
        # -------------------
        self.label2 = QLabel('リストを表示',self)
        self.label2.setFont(font)  # フォントを設定
        layout.addWidget(self.label2)
        
        # -------------------
        self.button2 = QPushButton('Close')
        self.button2.setFont(font)  # フォントを設定
        self.button2.clicked.connect(QApplication.quit)
        layout.addWidget(self.button2)

        # -------------------------------------
        # widgwetが画面上に表示される
        self.show
        
    # -----------------------------------------
    def show_selected(self):
        ans = None  # 他の関数（メソッド）で使用する為、初期値を与える
        for rb in self.radiobuttons:
            if rb.isChecked():# ラジオボタン（QRadioButton）の状態を1個ずつ確認するメソッド
                self.result_label.setText(f'選択結果：{rb.objectName()}')
                #print('#14')
                self.label2.setText(f'選択結果：{str(self.mylist[int(rb.objectName())-1])}')# ラジオボタンは1〜、リストは0〜のため-1で補正。またrb.objectName()はstrのためintへ変換
                #print('#15')
                ans = int(rb.objectName())# <--
                #print('#16')
                break
            #else:
                #print('#12')
                
        # -------------------------------------
        # ansをshow_selected2メソッドに渡す
        self.show_selected2(ans)
        
    # -----------------------------------------
    def show_selected2(self,ans):# ansを引数として使用
        if ans == None:  # もし初期値がNoneであれば何もしない
            print()

        else:

            # 辞書に変換
            files_dir = self.mylist
            key = []
            ln = len(files_dir)

            [key.append(i+1) for i in range(ln)]

            ele = files_dir
            dct = dict(zip(key, ele))

            # --------------------------------------
            # 辞書をdataframeへ変換
            dct2 = {'key':key, 'File':files_dir}
            df = pd.DataFrame(dct2,columns = ['key','File'],index = key)

            # --------------------------------------
            # 実行するディレクトリを選択する
            pr = df.loc[ans,'File']

            # --------------------------------------
            # 実行するディレクトリに移動
            os.chdir(path + '/'+pr)
            b = os.getcwd()
            print(f'現在のディレクトリは\n{b}\nです')

            # 実行
            sb.run(['python3', 'main.py'])
            # --------------------------------------

# ---------------------------------------------
if __name__ == '__main__':
   #main()
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    app.exec()
```


# 関係リンク
>**"ChatGPT for Mac" をインストールして使ってみた。**
https://qiita.com/ti104110/items/40563e13d9f389bd62bd
***
>**tkinter がうまくいかないので、PyQt6でWidget（ウィジェット）に挑戦（その１)**
https://qiita.com/ti104110/items/0c0800cff58cd10b9676
***
>**tkinter がうまくいかないので、PyQt6でWidget（ウィジェット）に挑戦（その２）RadioButtonで選択してWebを開く**
https://qiita.com/ti104110/items/7785758f98ef978c2d97
***
>**tkinter がうまくいかないので、PyQt6でWidget（ウィジェット）に挑戦（その３）QGridLayout()オブジェクトを使って、labelとQLineEditを横並びに表示**
https://qiita.com/ti104110/items/a35263176ff5ddaafac7
***
>**tkinter がうまくいかないので、PyQt6でウィジェットに挑戦（その５）「Googleの急上昇ワード」の表示に"QTextBrowser"でURLにリンク設定を追加**
https://qiita.com/ti104110/items/d9868846ff7ac9556edf



# あとがき
>pyqt6については記述方法が定型的なので大分慣れなしたが、今回は**実行するディレクトリに移動する**部分でChatGPTに教えてもらいました。
osモジュールについては、知らなかったのでこれを機会に勉強してみようと思います。