7. Line Edit & Dynamic Properties
今回は Line Edit とダイナミックプロパティなどについて解説していきますが、開発手段などは習得済みであると仮定しています。
ですので、PyQt に詳しくない方は、最初から読み直して下さい。
また、今回からはプログラミングについての説明も始めますが、Python に関する基礎知識は全て習得済みであると仮定して話を続けていきます。
今回利用するソースなどは次に纏めてあります。
Line Edit とは?
Line Edit とは1行だけで構成されるテキスト入力項目です。 ごく一般的な入力項目ですので使用されるケースが一番多いウィジェットです。QLineEdit
そこで今回は入力制限付きの Line Edit について確認していきます。
複数行のテキストを入力する場合は QTextEdit を利用して下さい。

また、パスワードなどの入力項目を表示したくない場合は、「echoMode」を「password」に設定して下さい。
Daynamic Property とは?
ダイナミックプロパティとは、すべてのウィジット(正確にはQObjectを継承するモノ)が所有できる独自のプロパティです。 文字列型や数字型なども設定できますので、C言語の #define を代用する事が可能です。
ウィジェットを選択し、「+」ボタンを押すことで、名前付きで設定できます。



property (name) でプロパティ名を指定するだけで取得が可能です。
ダイアログの作成
以下のようなダイアログを作成しました。


ここでパスワードの項目は文字列を直接表示したくないので、「echoMode」を「Password」に設定してあります。

ここで、パスワードの一致結果を表示するラベル(resultsLabel)には次のようなダイナミックプロパティを作成しました。

プログラミング
ソース(main.py)は、次の通りです。
#!/usr/bin/env python
# This Python file uses the following encoding: utf-8
import sys
import re
from PySide6.QtCore import Slot
from PySide6.QtWidgets import QApplication, QDialog
from PySide6.QtUiTools import loadUiType
class ColorDialog(QDialog):
    def __init__(self):
        # 親クラスの初期化
        super().__init__()
        # ダイアログファイルを読み込み専用でオープンし、ダイアログデータの読み込み
        generated_class, base_class = loadUiType("dialog.ui")
        self.form = generated_class()
        self.form.setupUi(self)
        # パスワード結果ラベルを設定
        value = self.form.resultsLabel.property('noPassword')
        self.form.resultsLabel.setText(value)
        # Line Edit に シグナル/スロット を設定
        self.form.numLineEdit.textChanged.connect(self.num_change)
        self.form.hiraganaLineEdit.textChanged.connect(self.hiragana_change)
        self.form.katakanaLineEdit.textChanged.connect(self.katakana_change)
        self.form.passwordLineEdit.textChanged.connect(self.password_change)
        self.form.confirmLineEdit.textChanged.connect(self.password_change)
    # 文字列(数字)が変更された時に実行するスレッド
    @Slot(str)
    def num_change(self, value):
        match = re.search(r'[^0-9]', value)
        if match:
            value = re.sub(r'[^0-9]', '', value)
            self.form.numLineEdit.setText(value)
    # 文字列(ひらがな)が変更された時に実行するスレッド
    @Slot(str)
    def hiragana_change(self, value):
        match = re.search(r'[^あ-んざ-ぞだ-どば-ぼぱ-ぽぁ-ぉゃ-ょっー]', value)
        if match:
            value = re.sub(r'[^あ-んざ-ぞだ-どば-ぼぱ-ぽぁ-ぉゃ-ょっー]', '', value)
            self.form.hiraganaLineEdit.setText(value)
    # 文字列(カタカナ)が変更された時に実行するスレッド
    @Slot(str)
    def katakana_change(self, value):
        match = re.search(r'[^ア-ンザ-ゾダ-ドバ-ボパ-ポァ-ォャ-ョッー]', value)
        if match:
            value = re.sub(r'[^ア-ンザ-ゾダ-ドバ-ボパ-ポァ-ォャ-ョッー]', '', value)
            self.form.katakanaLineEdit.setText(value)
    # 文字列(パスワード)が変更された時に実行するスレッド
    @Slot(str)
    def password_change(self, value):
        if 1 > len(self.form.passwordLineEdit.text()):
            value = self.form.resultsLabel.property('noPassword')
            self.form.resultsLabel.setText(value)
        elif self.form.passwordLineEdit.text() == self.form.confirmLineEdit.text():
            value = self.form.resultsLabel.property('matchPassword')
            self.form.resultsLabel.setText(value)
        else:
            value = self.form.resultsLabel.property('missmatchPassword')
            self.form.resultsLabel.setText(value)
if __name__ == "__main__":
    # アプリケーションの開始
    app = QApplication(sys.argv)
    # ダイアログの生成
    window = ColorDialog()
    # ダイアログの表示
    window.show()
    # イベントループの実行
    sys.exit(app.exec())
入力制限
入力制限は文字が入力された場合に発生するシグナル textChanged (arg__1) を利用しています。
ここで数字だけに制限する方法を見てみましょう。
    # 文字列(数字)が変更された時に実行するスレッド
    @Slot(str)
    def num_change(self, value):
        match = re.search(r'[^0-9]', value)
        if match:
            value = re.sub(r'[^0-9]', '', value)
            self.form.numLineEdit.setText(value)
正規表現で数字以外が入力された場合には、re.sub() を用いて、数字以外の部分を消去して setText (arg__1) で設定し直しています。
パスワードチェック
パスワードのチェックを見てみましょう。
    # 文字列(パスワード)が変更された時に実行するスレッド
    @Slot(str)
    def password_change(self, value):
        if 1 > len(self.form.passwordLineEdit.text()):
            value = self.form.resultsLabel.property('noPassword')
            self.form.resultsLabel.setText(value)
        elif self.form.passwordLineEdit.text() == self.form.confirmLineEdit.text():
            value = self.form.resultsLabel.property('matchPassword')
            self.form.resultsLabel.setText(value)
        else:
            value = self.form.resultsLabel.property('missmatchPassword')
            self.form.resultsLabel.setText(value)
ダイナミックプロパティから、空の場合は「noPassword」、同じ場合は「matchPassword」、それ以外では「missmatchPassword」を取得して表示しています。
シグナル/スロットの結合
前回同様に、シグナル textChanged (arg__1) を利用しますので以下の様になります。
    # Line Edit に シグナル/スロット を設定
    self.form.numLineEdit.textChanged.connect(self.num_change)
    self.form.hiraganaLineEdit.textChanged.connect(self.hiragana_change)
    self.form.katakanaLineEdit.textChanged.connect(self.katakana_change)
    self.form.passwordLineEdit.textChanged.connect(self.password_change)
    self.form.confirmLineEdit.textChanged.connect(self.password_change)また、今回のシグナルは文字列型ですので、スロットを作成する場合は「@Slot(str)」になります。
独自のスレッドの作成方法が判らない場合は前回の「6. Spin Box & Slider & CSS」を参考にしてください。
プロジェクト
プロジェクトは次の様になりました。

実行結果
実行結果は次の様になりました。

まとめ
今回は簡単な入力制限を行ってみました。参考になったでしょうか?
