第 11 章: 練習問題
この章では、各章で学んだ知識を実際に使って理解を深めるための練習問題を提供します。まずは自力で解いてみて、どうしても分からなければヒントや解答例の方針を参考にしてください。
練習問題 1 (第 3 章: シグナルとスロット)
課題:
QLineEditウィジェットとQLabelウィジェットを一つずつ配置したウィンドウを作成してください。QLineEditにテキストが入力されるたびに、その内容がリアルタイムでQLabelに反映されるようにしてください。
ヒント:
QLineEditには、テキストが変更されるたびにtextChangedというシグナルが発信されます。このシグナルは、変更後のテキスト(文字列)を引数として渡してくれます。
解答例の方針:
QMainWindowを継承したMainWindowクラスを作成します。__init__内でQLineEditとQLabelのインスタンスを作成し、レイアウトに配置します。update_label(self, text)のようなスロットメソッドをMainWindowクラスに定義します。このメソッドは引数textを受け取り、self.label.setText(text)を実行します。__init__内で、self.line_edit.textChanged.connect(self.update_label)のようにシグナルとスロットを接続します。
練習問題 2 (第 4 章: 主要なウィジェット)
課題: 摂氏(Celsius)を華氏(Fahrenheit)に変換する簡単な温度変換ツールを作成してください。UI には以下の要素を含めてください。
- 摂氏を入力するための
QLineEdit - 「変換」と書かれた
QPushButton - 変換結果の華氏を表示するための
QLabel
計算式: 華氏 = (摂氏 * 9/5) + 32
ヒント:
QLineEditからtext()メソッドで取得できるのは文字列です。計算するにはfloat()を使って浮動小数点数に変換する必要があります。また、QLabelに設定する際にはstr()で再び文字列に戻します。ユーザーが数字以外を入力した場合に備え、try-exceptブロックでエラー処理を行うと、より堅牢なアプリケーションになります。
解答例の方針:
- UI に
QLineEdit,QPushButton,QLabelを配置します。 QPushButtonのclickedシグナルを、計算処理を行うスロットメソッド(例:convert_temperature)に接続します。convert_temperatureメソッド内で、QLineEditからテキストを取得します。try-except ValueErrorブロックの中で、取得したテキストをfloat()で数値に変換します。- 計算式を使って華氏を計算します。
- 計算結果を
str()で文字列に変換し、f"結果: {result:.2f} °F"のようにフォーマットして結果表示用のQLabelに設定します。 exceptブロックでは、エラーメッセージをQLabelに表示するようにします。
練習問題 3 (第 5 章: ダイアログ)
課題:
複数行のテキストを入力できるQTextEditと、「メモを保存」ボタンを配置したウィンドウを作成してください。ボタンをクリックするとファイル保存ダイアログ(QFileDialog)が開き、ユーザーが指定したファイルにQTextEditの内容がテキストファイルとして保存されるようにしてください。
ヒント:
QFileDialog.getSaveFileName()を使うと、保存先のファイルパスを文字列として取得できます。ユーザーがダイアログをキャンセルした場合は空文字列が返るので、その場合は何もしないようにします。
解答例の方針:
- UI に
QTextEditとQPushButtonを配置します。 - ボタンの
clickedシグナルをsave_noteスロットに接続します。 save_noteスロット内でQFileDialog.getSaveFileName(self, "メモを保存", "", "Text Files (*.txt)")を呼び出します。- 戻り値のファイルパスが空でないことを確認します。
self.text_edit.toPlainText()でQTextEditの全テキストを取得します。- Python の標準的なファイル I/O (
with open(file_path, 'w', encoding='utf-8') as f:) を使って、取得したテキストをファイルに書き込みます。
練習問題 4 (第 6 章: アクション、メニュー、ツールバー)
課題: 練習問題 3 で作成したメモ帳アプリケーションを改良してください。「メモを保存」ボタンを削除し、代わりに以下の機能を追加してください。
- 「ファイル」メニューに「保存」メニュー項目を追加する。
- ツールバーに「保存」アイコンボタンを追加する。
- メニュー項目とツールバーボタンは、同じ「保存」アクションを共有するようにする。
ヒント:
QActionを一つ作成し、そのtriggeredシグナルを練習問題 3 で作成したsave_noteメソッドに接続します。そして、そのQActionインスタンスをQMenuとQToolBarの両方にaddAction()で追加します。
解答例の方針:
__init__内でQActionのインスタンス(例:save_action)を作成します。アイコン(QStyleの標準アイコンなど)、テキスト、ショートカット、ステータスチップを設定します。save_action.triggered.connect(self.save_note)のようにシグナルを接続します。self.menuBar()でメニューバーを取得し、「ファイル」メニューを追加後、file_menu.addAction(save_action)でアクションを追加します。QToolBarのインスタンスを作成してself.addToolBar()でウィンドウに追加し、toolbar.addAction(save_action)で同じアクションを追加します。- レイアウトから
QPushButtonを削除します。
練習問題 5 (第 7 章: モデル/ビュー)
課題: 簡単な ToDo リストアプリケーションを作成してください。UI の要件は以下の通りです。
- ToDo 項目を一覧表示する
QListView。 - 新しい項目を入力する
QLineEdit。 - 「追加」と書かれた
QPushButton。
「追加」ボタンを押すと、QLineEditに入力されたテキストがQListViewのリストの末尾に追加されるようにしてください。
ヒント:
データと表示を分離するため、QListWidgetではなくQListViewとQStringListModelを使用してください。QStringListModelのstringList()で現在のリストを Python のリストとして取得し、setStringList()で更新されたリストをモデルに再設定します。
解答例の方針:
- UI に
QListView,QLineEdit,QPushButtonを配置します。 __init__内で、self.model = QStringListModel([])のように空のモデルを作成し、self.list_view.setModel(self.model)でビューに設定します。- 「追加」ボタンの
clickedシグナルをadd_todo_itemスロットに接続します。 add_todo_itemスロット内で、QLineEditから新しい項目テキストを取得します。current_list = self.model.stringList()で現在のリストを取得します。current_list.append(new_item_text)で新しい項目を追加します。self.model.setStringList(current_list)でモデルを更新します。ビューは自動的に更新されます。self.line_edit.clear()で入力欄をクリアします。