見出し画像

PythonでChatGPTと一緒に住所録を作ろう:機能追加 保存

前回まででJSONデータを取り込むことができるようになりました。

あとは、フィルター、新規追加、編集、削除、保存ができるように機能を追加していきます。

今回は、データの保存機能を追加します。


1.データの保存

データの保存機能を追加します。

ChatGPTに以下のプロンプトを送信してください。
(前回までのコードを貼り付けて)住所録のコードです。
データを保存できるようにメソッドを作ってください
。」

ChatGPTの作ってくれたコードは以下のとおりです。

    def save_data_to_json(self):
        data = []
        for row in range(self.table.rowCount()):
            entry = {
                "姓": self.table.item(row, 0).text() if self.table.item(row, 0) else "",
                "姓フリガナ": self.table.item(row, 1).text() if self.table.item(row, 1) else "",
                "名": self.table.item(row, 2).text() if self.table.item(row, 2) else "",
                "名フリガナ": self.table.item(row, 3).text() if self.table.item(row, 3) else "",
                "郵便番号": self.table.item(row, 4).text() if self.table.item(row, 4) else "",
                "住所": self.table.item(row, 5).text() if self.table.item(row, 5) else "",
                "電話番号": self.table.item(row, 6).text() if self.table.item(row, 6) else "",
                "備考": self.table.item(row, 7).text() if self.table.item(row, 7) else ""
            }
            data.append(entry)
        
        with open("address_book.json", "w", encoding="utf-8") as file:
            json.dump(data, file, ensure_ascii=False, indent=4)
        print("データを保存しました")

save_data_to_json() メソッドを、コードへ組み込みます。
クラスAddressBookApp の適当な場所にこのメソッドを追加します。
保存するファイル名 "address_book.json" を上書きしないように
"address_book_save.json" などの様に名前を変えておきます。

もう、一か所

        self.save_button.clicked.connect(self.save_data_to_json)

このコードを setup_ui() メソッドの最後に追加してください。
これで"保存"ボタンをしたときに save_data_to_json() メソッドが実行されます。

これで住所録を起動して保存ボタンを押してみましょう。

内容を確認してください。
うまく行ったでしょうか。

2.コード解説

A.save_data_to_json()

        for row in range(self.table.rowCount()):
            entry = {
                "姓": self.table.item(row, 0).text() if self.table.item(row, 0) else "",
                "姓フリガナ": self.table.item(row, 1).text() if self.table.item(row, 1) else "",
                "名": self.table.item(row, 2).text() if self.table.item(row, 2) else "",
                "名フリガナ": self.table.item(row, 3).text() if self.table.item(row, 3) else "",
                "郵便番号": self.table.item(row, 4).text() if self.table.item(row, 4) else "",
                "住所": self.table.item(row, 5).text() if self.table.item(row, 5) else "",
                "電話番号": self.table.item(row, 6).text() if self.table.item(row, 6) else "",
                "備考": self.table.item(row, 7).text() if self.table.item(row, 7) else ""
            }
            data.append(entry)

self.table.rowCount()
これは、テーブルの行数なので
行数分forループを繰り返します。
そのたびにentryという辞書が作られます。

内容は、列数分あります。
の部分を一行だけ説明します。

"姓": self.table.item(row, 0).text() if self.table.item(row, 0) else "",

この書き方は、三項演算子と言う書き方です。
ChatGPTで確認しておきましょう。

if self.table.item(row, 0):
    self.table.item(row, 0).text()
else:
    ""

と同じ意味になります。

つまり、1列目に値があればその文字列を取得し、
なければ空文字を設定する。
という事になります。

同じ事を8列分繰り返して出来上がった辞書1項目分を
dataに追加して住所録のリストを作ります。

        with open("address_book.json", "w", encoding="utf-8") as file:
            json.dump(data, file, ensure_ascii=False, indent=4)

"address_book.json"をテキスト形式で開いて
dataリストをjson形式で書き出します。

json.dump()の内容をChatGPTで押さえておきましょう。

ensure_ascii=False とすると日本語でファイルに出力されます。
indent=4 は、字下げをスペース4個分にする設定です。

B.connect()

        self.save_button.clicked.connect(self.save_data_to_json)

save_buttonをクリックしたときに
save_data_to_json() を実行します。

3.全コード

"address_book.json" をコードの頭の方へ
モジュール変数として定義しなおしました。

DATA_FILE = "address_book.json"

モジュール変数グローバル変数の動作の違いをChatGPTで確認しましょう。
この辺がPythonは、ややこしいですね。
バグを生みやすい部分。

A.コード

import sys
import json
from PyQt6.QtWidgets import (
    QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
    QTableWidget, QTableWidgetItem, QHeaderView, QWidget, QLabel, QDialog, QFormLayout
)

DATA_FILE = "address_book.json"

class EditDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("編集画面")
        self.setGeometry(200, 200, 400, 300)

        layout = QFormLayout()

        self.last_name_input = QLineEdit()
        self.first_name_input = QLineEdit()
        self.last_name_kana_input = QLineEdit()
        self.first_name_kana_input = QLineEdit()
        self.postal_code_input = QLineEdit()
        self.address_input = QLineEdit()
        self.phone_number_input = QLineEdit()
        self.notes_input = QLineEdit()

        layout.addRow("姓", self.last_name_input)
        layout.addRow("名", self.first_name_input)
        layout.addRow("姓フリガナ", self.last_name_kana_input)
        layout.addRow("名フリガナ", self.first_name_kana_input)
        layout.addRow("郵便番号", self.postal_code_input)
        layout.addRow("住所", self.address_input)
        layout.addRow("電話番号", self.phone_number_input)
        layout.addRow("備考", self.notes_input)

        self.save_button = QPushButton("保存")
        self.cancel_button = QPushButton("キャンセル")

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.save_button)
        button_layout.addWidget(self.cancel_button)
        layout.addRow(button_layout)

        self.setLayout(layout)

class AddressBookApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("住所録")
        self.setGeometry(100, 100, 800, 600)

        # GUIを構築
        self.setup_ui()

        # データを読み込む
        self.load_data_from_json(DATA_FILE)

    def setup_ui(self):
        """GUIを構築するメソッド"""
        # メインウィジェットとレイアウト
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        main_layout = QVBoxLayout()
        main_widget.setLayout(main_layout)

        # フィルター入力と実行ボタン
        filter_layout = QHBoxLayout()
        self.filter_input = QLineEdit()
        self.filter_input.setPlaceholderText("フィルターを入力")
        self.filter_button = QPushButton("実行")
        filter_layout.addWidget(self.filter_input)
        filter_layout.addWidget(self.filter_button)
        main_layout.addLayout(filter_layout)

        # 一覧表
        self.table = QTableWidget()
        self.table.setColumnCount(8)
        self.table.setHorizontalHeaderLabels([
            "姓", "姓フリガナ", "名", "名フリガナ", "郵便番号", "住所", "電話番号", "備考"
        ])
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        main_layout.addWidget(self.table)

        # ボタン群
        button_layout = QHBoxLayout()
        self.new_button = QPushButton("新規作成")
        self.edit_button = QPushButton("編集")
        self.delete_button = QPushButton("削除")
        self.save_button = QPushButton("保存")
        self.load_button = QPushButton("読み込み")
        
        button_layout.addWidget(self.new_button)
        button_layout.addWidget(self.edit_button)
        button_layout.addWidget(self.delete_button)
        button_layout.addWidget(self.save_button)
        button_layout.addWidget(self.load_button)
        main_layout.addLayout(button_layout)

        # ボタンの動作設定
        self.new_button.clicked.connect(self.open_edit_dialog)
        self.edit_button.clicked.connect(self.open_edit_dialog)
        self.save_button.clicked.connect(self.save_data_to_json)

    def load_data_from_json(self, file_path):
        try:
            # JSONデータの読み込み
            with open(file_path, "r", encoding="utf-8") as file:
                address_book = json.load(file)

            # データをテーブルに追加
            self.table.setRowCount(len(address_book))  # 行数を設定
            for row, entry in enumerate(address_book):
                for col, item in enumerate(["姓", "姓フリガナ", "名", "名フリガナ",
                                            "郵便番号","住所", "電話番号", "備考"]):
                    cell = QTableWidgetItem(entry.get(item, ""))
                    self.table.setItem(row, col, cell)
        except FileNotFoundError:
            print("ファイルが見つかりません。")
        except json.JSONDecodeError:
            print("JSONデータが壊れています")
    
    def save_data_to_json(self):
        data = []
        for row in range(self.table.rowCount()):
            entry = {
                "姓": self.table.item(row, 0).text() if self.table.item(row, 0) else "",
                "姓フリガナ": self.table.item(row, 1).text() if self.table.item(row, 1) else "",
                "名": self.table.item(row, 2).text() if self.table.item(row, 2) else "",
                "名フリガナ": self.table.item(row, 3).text() if self.table.item(row, 3) else "",
                "郵便番号": self.table.item(row, 4).text() if self.table.item(row, 4) else "",
                "住所": self.table.item(row, 5).text() if self.table.item(row, 5) else "",
                "電話番号": self.table.item(row, 6).text() if self.table.item(row, 6) else "",
                "備考": self.table.item(row, 7).text() if self.table.item(row, 7) else ""
            }
            data.append(entry)
        
        with open("address_book.json", "w", encoding="utf-8") as file:
            json.dump(data, file, ensure_ascii=False, indent=4)
        print("データを保存しました")

            
    def open_edit_dialog(self):
        dialog = EditDialog(self)
        dialog.exec()
                
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = AddressBookApp()
    window.show()
    sys.exit(app.exec())

まとめ

ここまでで、データの保存ができる様になりました。

次回は、"新規作成"でデータを追加できる様にします。

お楽しみに。

いいなと思ったら応援しよう!