
PythonでChatGPTと一緒に住所録を作ろう:画面作成
PythonでChatGPTを使いながら住所録を作ろうといった企画です。
何回かに分けて記事を書く予定です。
この記事で学習することで実用的GUIなアプリケーションの基本が分かります。
また、自分で調べながらアプリケーションを作ることが出来る様になります。
目標は、住所録の検索(フィルター) 、登録、編集、削除、保存、読み込みが出来ること。
いきなりデータベースは、難しいので json をデータの保存につかいその読み書きができることです。
画面は、下の2画面とします。


1.進め方
下のようなプロンプトを送るとChatGPTは、一度で狙ったものに近いものを作れてしまいます。
「 [添付したjsonデータ見本] このような形式のデータファイルを読み込んでデータにする
そして保存できるデータは行を選択して削除、編集が出来る新規追加出来る データの読み込みが出来る
画面は、上部にフィルター入力欄とフィルターの実行ボタンがあるその下は住所録の一覧を表形式で 姓、姓フリガナ、名、名フリガナ、郵便番号、住所、電話番号、備考 の列がある。
最下行には、新規作成、編集、削除、保存、読み込みのボタンが並んでいる。
以上の機能のある住所録を作って 」

問題点は、削除がうまくできていなかったぐらいです。
ですが、今まで経験上わかっているのは大きく複雑になっていく(200行程度過ぎると)と一度で正確に作るのが難しくなります。
そして、一か所を修正すると別の部分が書き換わってしまったりうまくゆかなくなってきます。
そういった使い方より、まずは骨子を作成しそこから機能を足していくほうがスムーズに作成できます。
そして、理解しながら進めることができます。
この方法であれば大きなアプリケーションであっても無理なく構築していくことができます。
ですので、まずは画面を作りそこから必要な機能を足していくという方針で進めます。
では、はじめましょう。
2.構成の決定
どんな風に作ればいいのかChatGPTに聞きました。
「住所録の管理ツールを作りたい
一覧画面とその内容を編集する画面の2画面構成にします。
どのようなライブラリを使いますか?」
回答は、長いのでまとめだけ表示します。まとめは、以下の通りです。
「提案する構成
PyQt6: GUI構築。
SQLite: データ保存と読み込み。
必要に応じて SQLAlchemy や Pandas を導入。
これらを組み合わせることで、住所録管理ツールを柔軟に構築できます。
どの部分から始めたいか、あるいは構造をもっと具体化したい場合は教えてください!」
このような回答が返ってきました。
今回は、一度にSQLを学ぶのは難しいのでデータベース代わりにjsonを使います。
そして、PyQt6の代わりにTkinterを進めてくる場合もあるのですが
少し複雑な事をコードが複雑になったり、動きが重くなる場合があるので
PyQt6を使うことにします。
3.環境設定
A.開発環境
今回試した環境は、以下の通りです。
Windows10
python 3.12.5
pyqt6 6.8.0
B.pyqt6のインストール
pip install pyqt6
C.pythonの仮想環境とVSCode
それと前提として、以前の記事に従った環境を用意しているとします。
違う環境の場合、適宜読み替えてください。
D.Qt for Python ドキュメント
ChatGPTに同時にこちらのドキュメントも頼りにしてください。
4.画面作成
まずは、一覧表の画面をChatGPTに作ってもらいます。
ChatGPT 以下のプロンプトを送りました。
「pyqt6で住所録の画面を作ってほしい
先ずは一覧表を作ってほしい
画面一番上にはフィルターの入力画面と実行ボタン
その下には一覧表で
列は 姓、姓フリガナ、名、名フリガナ、郵便番号、住所、電話番号、備考 画面下には新規作成、編集、削除、保存、読み込みのボタンがある」

作成されたコードを実行すると上のような画面になりました。
しかし、思った通りにプロンプトだけで画面を作ってくれるなんてもうAIは手放せませんね。
さらに、
「新規ボタン・編集ボタンを押したときに切り替わる編集画面を作って」
とプロンプトを送ったところ以下のコードが出来上がりました。
5.画面コード
import sys
from PyQt6.QtWidgets import (
QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
QTableWidget, QTableWidgetItem, QHeaderView, QWidget, QLabel, QDialog, QFormLayout
)
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)
# メインウィジェットとレイアウト
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)
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())

同一スレッドのプロンプトなので同一のアプリケーションへのプロンプトと認識し、
2画面を持った住所録のコードが作成されました。
6.ChatGPTによる解説
ChatGPTに
「解説してください。」
とプロンプトを送ります。
##################################
ここからは、ChatGPTの回答 ####################
##################################
このコードは、PyQt6 を使用して「住所録アプリ」を構築するための基本的な GUI アプリケーションです。それぞれの部分について詳細に解説します。
1. 必要なモジュールのインポート
import sys
from PyQt6.QtWidgets import (
QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
QTableWidget, QTableWidgetItem, QHeaderView, QWidget, QLabel, QDialog, QFormLayout
)
PyQt6のウィジェット(GUIを作成するための部品)をインポートしています。
QApplication: アプリケーション全体の制御を担当します。
QMainWindow: メインウィンドウを作成します。
QVBoxLayout/QHBoxLayout: 垂直/水平レイアウトを構築するためのレイアウトマネージャです。
QLineEdit: ユーザーがテキストを入力するためのウィジェットです。
QPushButton: ボタンを作成します。
QTableWidget: 表形式でデータを表示するウィジェットです。
QDialog: ダイアログ(モーダルウィンドウ)を作成するためのベースクラスです。
QFormLayout: ラベルと入力フィールドをペアで配置するためのレイアウトです。
2. 編集画面(EditDialog クラス)
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)
目的: 新規作成または編集時に使う入力ダイアログ画面を作成します。
フィールド: 姓、名、フリガナ、郵便番号、住所、電話番号、備考などの入力フィールドを持っています。
ボタン: 「保存」と「キャンセル」の2つのボタンを持ち、QHBoxLayout で横並びに配置しています。
3. メインアプリケーション(AddressBookApp クラス)
初期化
class AddressBookApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("住所録")
self.setGeometry(100, 100, 800, 600)
メインウィンドウのタイトルとサイズを設定します。
レイアウトとウィジェットの設定
main_widget = QWidget()
self.setCentralWidget(main_widget)
main_layout = QVBoxLayout()
main_widget.setLayout(main_layout)
QMainWindow にメインウィジェットを設定し、全体のレイアウトを QVBoxLayout(縦並び)で管理します。
フィルター入力
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)
ユーザーがフィルター条件を入力するための QLineEdit と、それを実行するためのボタンを作成します。
データテーブル
self.table = QTableWidget()
self.table.setColumnCount(8)
self.table.setHorizontalHeaderLabels([
"姓", "姓フリガナ", "名", "名フリガナ", "郵便番号", "住所", "電話番号", "備考"
])
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
main_layout.addWidget(self.table)
データを表示するための表形式ウィジェット(QTableWidget)を作成します。8列のカラムとカラム名を設定しています。
ボタン群
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)
新規作成、編集、削除、保存、読み込みの5つのボタンを作成し、横並びに配置します。
ボタンの動作
self.new_button.clicked.connect(self.open_edit_dialog)
self.edit_button.clicked.connect(self.open_edit_dialog)
「新規作成」または「編集」ボタンがクリックされたときに open_edit_dialog メソッドを実行します。
4. ダイアログを開くメソッド
def open_edit_dialog(self):
dialog = EditDialog(self)
dialog.exec()
編集用ダイアログを開きます。このダイアログはモーダルウィンドウとして表示されます(元のウィンドウは操作不可)。
5. エントリーポイント
if __name__ == "__main__":
app = QApplication(sys.argv)
window = AddressBookApp()
window.show()
sys.exit(app.exec())
アプリケーションを実行するためのエントリーポイントです。QApplication オブジェクトを作成し、AddressBookApp ウィンドウを表示します。
全体の流れ
メインウィンドウ (AddressBookApp) が立ち上がり、住所録の表と操作ボタンが表示される。
「新規作成」または「編集」を押すと、編集用ダイアログ (EditDialog) が開き、データを入力・編集できる。
保存・読み込みなどの機能を追加していくことで、完全な住所録アプリが完成する。
このコードは住所録アプリの基本構造を持つテンプレートとして使用できます。
##################################ChatGPTの回答終わり #######################
##################################
7.さらに深堀
A.動かしてみる
先ずは、コードをVSCodeで動かしてみましょう。
で、動作確認をしてみましょう。
それらしい画面が表示されますが
"新規" ”編集”ボタン以外は、何も反応が無いことを確認してください。
"新規" ”編集”ボタンを押したときは、編集画面が表示されますね。
B.ChatGPTの解説を読む
"1. 必要なモジュールのインポート"
ここでは、import文で
色々と重要なものが読み込まれ、それぞれがどんな役割を果たしているか
かいつまんで説明されています。
import sys
from PyQt6.QtWidgets import (
QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
QTableWidget, QTableWidgetItem, QHeaderView, QWidget, QLabel, QDialog, QFormLayout
)
この部分についての解説ですね。
以下、ごろう解説部分は”ご : "とします。
ChatGPT : PyQt6のウィジェット(GUIを作成するための部品)をインポートしています。
ご : いろいろと読み込んでいるものはPyQt6のGUI部品であると言ってますね。
ChatGPT : QApplication: アプリケーション全体の制御を担当します。
ご : この説明だけだと良くわかりませんね。「QApplicationの役割を詳しく解説して」とプロンプトを送りましょう。
ご : そうすると、
イベントループの管理
アプリケーションの初期化
グローバルリソースの管理
メインウィンドウの表示
等と返ってきます。
何のためにあるか理解できたでしょうか。
ご : 「PyQt6での最小のGUIアプリケーションのサンプルコードを書いて?」などとして、最小コードを確認しましょう。
より一層理解が深まります。
部品の説明部分
ご : 全て詳細に調べなくても興味のあるところだけ、調べておきましょう。
あとから理解できなくなったときに調べれば大丈夫です。
ChatGPT : QMainWindow: メインウィンドウを作成します。
ご : "QMainWindowとは?"と聞いてみましょう。
また、"QWidgetとはどう使い方が違うのか?”を確認してみましょう。
QWidgetもQMainWindowの代わりに使えること。
QMainWindowは、アプリケーションとして必要な機能が備えられていることを確認しましょう。
ChatGPT : QVBoxLayout/QHBoxLayout: 垂直/水平レイアウトを構築するためのレイアウトマネージャです。
ご : レイアウトマネージャーの種類を確認しましょう。
主に4種類があるので確認しましょう。
ChatGPT : QLineEdit: ユーザーがテキストを入力するためのウィジェットです。
ご : どのような機能があるか複数行のテキストはどのように入力するか確認しておきましょう。
ChatGPT : QPushButton: ボタンを作成します。
ChatGPT : QTableWidget: 表形式でデータを表示するウィジェットです。
ご : 行と列の生成、データの編集方法、行と列のヘッダーの表示方法などを確認しておきましょう。
ChatGPT : QDialog: ダイアログ(モーダルウィンドウ)を作成するためのベースクラスです。
ChatGPT : QFormLayout: ラベルと入力フィールドをペアで配置するためのレイアウトです。
ご : ここまで調べたところで「PyQt6の画面の構成方法を解説して」とプロンプトを送って、画面を組み立てる方法を確認してみましょう。
これだけで、代替画面の作り方を理解できるはずです。
試しに簡単な画面を自分で作ってみて動かなければChatGPTに添削してもらいましょう。
"2.編集画面(EditDialog クラス)"
ご : まだ、Pythonのクラスにについて自身のない場合は以下の様にプロンプトを送ってください。
「EditDialogクラスを参考にPythonでのクラスの作り方について教えてください。また、なぜクラスにするのかを解説してください。」
クラスの継承の仕方
コンストラクタの意味
カプセル化とその役割
ご : コンストラクタでは、
__init__() と super.__init__()
の意味を確認してください。
ご : ChatGPTの説明では分かりづらい方の為に、画面の組み立て方について
詳しく見ていきましょう。
class EditDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
...
ご : 作られたEditDialogクラスは、QDialogクラスを継承しています。
継承するとは、QDialog クラスの内容がそのまま引き継がれていますという事です。
ご : なので内部のデータや関数(クラスの場合メソッドと言うのが正しいです)を全て引き継いだという事です。
ご : 継承と言うのは、引き継いだクラスに対して新しくメソッドを書き足したり
上書きして書き直したりすることを言います。
ご : このことで親クラスとは、機能を変更したり加えたりすることができます。
def __init__(self, parent=None):
super().__init__(parent)
ご : この2行でクラスを初期化しています。
初期化とは、クラスの内部の状態をインスタンス化する際に整える操作のことです。
def __init__(self, parent=None):
ご : この部分の第一引数selfは、クラス内のメソッドにはかならず必要で
メソッド内部でselfを使うために必ず設定します。
parent=None は、この場合QDialogは親のない独立したWindowなのでNoneになっています。
ご : コンストラクタの中でまずQFormLayoutをつくりっています。
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)
ご : layoutと設定したQFormLayoutに
入力に必要なだけQLineEditを用意して
layoutへaddRowメソッドでラベルと組で詰め込んでいきます。
ご : layoutの中には、ラベルと組の入力欄が8行分並べられた状態になりました。
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
ご : 次は、ボタンを2つ作り
QHBoxLayout()に詰め込んでいます。
これは、水平に並べるレイアウトです。
そしてこのライアウトつまり並べたボタンをさらに先ほどのQFormLayoutに
追加しました。
self.setLayout(layout)
ご : 最後にselfにlayoutつまりQFormLayoutを追加しています。
selfは、自分自身つまりQDialogですのでダイアログ画面に
全ての要素が配置されることになります。
"3.メインアプリケーション(AddressBookApp クラス)"
ご : 繰り返しになるの部品の組み立てに関してはEditDialogを参考にしてみてください。
QDialogがQMainWindowになっていますがだいたい同じ構成です。
ご : 注意すべき点としてQMainWindowでは、メイン部分のWidgetの設定にsetCentralWidget()を使います。
ご : QTableWidgetは、複雑で機能も多いので必要なメソッドをしっかり押さえておきましょう。
.setItem(row, column, QTableWidgetItem("内容")): セルにデータを追加
.rowCount()や.columnCount(): 行や列の数を取得
.removeRow(row): 行を削除
.selectedItems(): 選択中のアイテムを取得
# ボタンの動作
self.new_button.clicked.connect(self.open_edit_dialog)
self.edit_button.clicked.connect(self.open_edit_dialog)
def open_edit_dialog(self):
dialog = EditDialog(self)
dialog.exec()
ご : ボタンを押したときなどの機能部分については、次回以降に学んでいきます。
"5.エントリーポイント"
1:if __name__ == "__main__":
2: app = QApplication(sys.argv)
3: window = AddressBookApp()
4: window.show()
5: sys.exit(app.exec())
ご : 先のChatGPTの説明だと全くわからないのでコードとともに
「詳しく説明してください。」としましょう。
重要なことが詰まっています。
ご : 1行目の書き方で特殊変数とは何かとどんな時にどんな値が返ってくるのかを抑えましょう。
ご : sys.argvとは何かを確認しましょう。
python address_book.py data.json
とした場合、sys.argv[1]には文字列"data.json"が入ります。
ご : sys.exit(app.exec())となぜ書くのか確認しましょう。
app.exec()が先に終了してコードを返すのでsys.exit()が動作するという流れを理解しましょう。
まとめ
いかがだったでしょうか?
ChatGPTにプロンプトを送りアプリケーションの画面を2画面作りました。
そして、コードの中身を読んでどのように画面が出来ているのかを知ることが出来ました。
それとともにPythonのいくつかの仕組みやPyQt6でのGUIアプリケーションの大まかな流れを知ることが出来ました。
次回は、アプリケーションの機能を画面に足しながら実用的なものに作り上げていきます。
お楽しみに。