Qt SpinBoxとは?基本的な使い方を徹底解説

はい、承知いたしました。QtフレームワークにおけるQSpinBoxウィジェットについて、約5000語の詳細な解説記事を作成します。


Qt SpinBoxとは? 数値入力ウィジェットの基本から応用まで徹底解説

はじめに:GUIにおける数値入力の重要性

現代のソフトウェアにおいて、ユーザーインターフェース(UI)はソフトウェアの使いやすさを大きく左右する要素です。特に数値入力を求める場面は頻繁にあります。例えば、設定値の変更、数量の指定、範囲の入力などです。このような場面で、ユーザーが直接キーボードから数値を入力する方法もありますが、入力ミスを防ぎ、操作を容易にするための専用ウィジェットがしばしば利用されます。

Qtフレームワークは、クロスプラットフォームなGUIアプリケーション開発のための強力なツールキットです。Qtは、様々な種類のウィジェット(GUI部品)を提供しており、その中には数値入力を専門とするウィジェットも含まれています。本記事で詳細に解説するQSpinBoxは、整数値の入力を扱うための標準的なウィジェットです。

QSpinBoxは、テキストフィールドと、値を増減させるための上下の矢印ボタン(スピンボタン)を組み合わせたものです。ユーザーは直接数値を入力することも、矢印ボタンを使って値を段階的に変更することもできます。これにより、入力の手間を省き、入力可能な値の範囲を制限することでエラーを防ぐことができます。

この記事では、QtのQSpinBoxについて、その基本的な使い方から、表示形式のカスタマイズ、操作性の設定、関連するウィジェットとの連携、さらには実践的な応用例まで、網羅的に解説します。Qtを使ったアプリケーション開発において、数値入力を扱う際の強力な味方となるQSpinBoxをマスターしましょう。

1. QSpinBoxの基本

1.1 QSpinBoxとは何か?

QSpinBoxは、あらかじめ定義された範囲内の整数値をユーザーに入力させるためのウィジェットです。テキストエディタと上下の矢印ボタン(スピンボタン)から構成されます。

  • テキストエディタ: 現在の値を表示し、ユーザーが直接数値を入力することもできます。
  • スピンボタン: 上ボタンをクリックすると値が増加し、下ボタンをクリックすると値が減少します。増減のステップ幅は設定可能です。

QSpinBoxは、整数の取り扱いに特化しており、浮動小数点数を扱う場合は後述のQDoubleSpinBoxを使用します。

1.2 必要なモジュールのインポート

QtアプリケーションでQSpinBoxを使用するには、Qtウィジェットモジュールをインポートする必要があります。PythonのPyQtやPySideを使用する場合、通常は以下のように記述します。

“`python
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QSpinBox, QLabel

または

from PyQt6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QSpinBox, QLabel

“`

C++の場合、ヘッダファイルをインクルードします。

“`cpp

include

include // レイアウトを使用する場合

include // ウィジェットを使用する場合

include // ラベルを使用する場合

“`

この記事では主にPython (PyQt/PySide) でのコード例を示しますが、概念はC++でも同様です。

1.3 QSpinBoxのインスタンス化とウィンドウへの配置

QSpinBoxを使用するには、まずインスタンスを作成します。親ウィジェットを指定することもできます。

python
spin_box = QSpinBox()

作成したQSpinBoxをウィンドウに表示するには、レイアウトマネージャーを使用して配置するか、親ウィジェットを直接指定します。一般的なアプリケーションでは、レイアウトを使って複数のウィジェットを整理します。

“`python
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QSpinBox, QLabel

class MainWindow(QMainWindow):
def init(self):
super().init()

    self.setWindowTitle("QSpinBox Basic Example")
    self.setGeometry(100, 100, 300, 200)

    layout = QVBoxLayout()

    label = QLabel("値を入力してください:")
    layout.addWidget(label)

    self.spin_box = QSpinBox()
    layout.addWidget(self.spin_box)

    central_widget = QWidget()
    central_widget.setLayout(layout)
    self.setCentralWidget(central_widget)

if name == “main“:
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
“`

このコードでは、QSpinBoxを一つ作成し、QVBoxLayout(垂直方向のレイアウト)に追加しています。QLabelを追加することで、ユーザーに何を入力すべきか指示しています。このレイアウトをメインウィンドウのセントラルウィジェットに設定することで、QSpinBoxがウィンドウ内に表示されます。

実行すると、デフォルトの設定でQSpinBoxが表示されます。デフォルトの範囲は0から99、初期値は0、ステップ幅は1です。

1.4 値の設定と取得

QSpinBoxの現在の値を取得したり、プログラムから値を設定したりすることができます。

  • 現在の値を取得: value() メソッドを使用します。
  • 値を設定: setValue(int value) メソッドを使用します。

“`python

値を取得

current_value = self.spin_box.value()
print(f”現在の値: {current_value}”)

値を設定

self.spin_box.setValue(50)
print(f”設定後の値: {self.spin_box.value()}”)
“`

setValue() メソッドに渡される値が、設定されている範囲外の場合は、自動的に範囲内の最も近い値に調整されます。例えば、最大値が100のQSpinBoxに200を設定しようとすると、値は100になります。

1.5 値の範囲設定

QSpinBoxの重要な機能の一つは、入力可能な値の範囲を設定できることです。これにより、無効な入力値を排除できます。

  • 最小値を設定: setMinimum(int min) メソッドを使用します。
  • 最大値を設定: setMaximum(int max) メソッドを使用します。
  • 範囲をまとめて設定: setRange(int min, int max) メソッドを使用します。

“`python

最小値と最大値を設定

self.spin_box.setMinimum(10)
self.spin_box.setMaximum(150)

または

self.spin_box.setRange(10, 150)

範囲を取得

min_val = self.spin_box.minimum()
max_val = self.spin_box.maximum()
print(f”設定された範囲: {min_val} から {max_val}”)
“`

デフォルトの範囲は0から99です。必要に応じて適切な範囲を設定してください。設定した範囲外の値をsetValue()で設定しようとした場合、値は自動的に範囲内にクランプ(制限)されます。また、ユーザーがスピンボタンや直接入力で範囲外の値を入力しようとした場合も、範囲内に制限されます。

1.6 ステップ幅の設定

スピンボタンをクリックしたときに、値がどれだけ増減するかを指定できます。これはステップ幅(single step)と呼ばれます。

  • ステップ幅を設定: setSingleStep(int step) メソッドを使用します。

“`python

ステップ幅を5に設定

self.spin_box.setSingleStep(5)

ステップ幅を取得

step = self.spin_box.singleStep()
print(f”設定されたステップ幅: {step}”)
“`

デフォルトのステップ幅は1です。例えば、ステップ幅を5に設定すると、上ボタンで値が5ずつ増加し、下ボタンで5ずつ減少します。ユーザーがキーボードの上下矢印キーを押した場合も、このステップ幅で値が変化します。

1.7 信号とスロット:値の変化を検知する

QSpinBoxは、値が変化したときに信号(signal)を発行します。この信号をキャッチし、特定のアクション(スロット)を実行させることで、値の変化にプログラムを応答させることができます。QSpinBoxには、値の変化を通知する主に二つの信号があります。

  • valueChanged(int i): 値が整数として変化したときに発行されます。引数として新しい整数値が渡されます。
  • valueChanged(QString text): 値が表示用のテキストとして変化したときに発行されます。引数として新しい値の文字列が渡されます(接頭辞、接尾辞、桁区切りなども含む)。

通常、プログラムで値そのものを処理したい場合は valueChanged(int) を、表示されているテキストに基づいて何かをしたい場合は valueChanged(QString) を使用します。

信号をスロットに接続するには、signal.connect(slot) の形式を使います。

“`python

値が変化したときに呼び出されるスロット関数

def on_value_changed(new_value):
print(f”値が変化しました: {new_value}”)

valueChanged(int) 信号をスロット関数に接続

self.spin_box.valueChanged.connect(on_value_changed)

必要に応じて valueChanged(QString) も接続可能

def on_text_changed(new_text):

print(f”表示テキストが変化しました: {new_text}”)

self.spin_box.valueChanged[str].connect(on_text_changed) # PyQt/PySideではオーバーロードされた信号はリストのようにアクセス

“`

このコードでは、on_value_changed という関数を定義し、spin_box.valueChanged 信号に接続しています。QSpinBoxの値がユーザー操作や setValue() によって変更されるたびに、on_value_changed 関数が呼び出され、新しい値が引数として渡されます。

2. 表示形式のカスタマイズ

QSpinBoxは、値の表示形式をカスタマイズするためのいくつかの機能を提供します。

2.1 接頭辞 (Prefix) と接尾辞 (Suffix)

表示される値の前後に特定の文字列(単位など)を追加できます。

  • 接頭辞を設定: setPrefix(str prefix) メソッドを使用します。
  • 接尾辞を設定: setSuffix(str suffix) メソッドを使用します。

“`python

接頭辞と接尾辞を設定

self.spin_box.setPrefix(“$”)
self.spin_box.setSuffix(” USD”)

設定を解除するには空文字列を設定

self.spin_box.setPrefix(“”)

self.spin_box.setSuffix(“”)

“`

例えば、上記の設定をすると、値が100の場合、表示は「$100 USD」のようになります。ただし、value() メソッドで取得できる値は純粋な数値(100)であり、接頭辞や接尾辞は含まれません。これらの文字列は表示のためだけに付加されます。

注意点として、接尾辞を設定した場合、その文字列は編集可能なテキストの一部として扱われることがあります。例えば、” kg” という接尾辞を設定し、ユーザーがテキスト部分を編集しようとすると、” kg” の部分も選択や削除の対象になることがあります。これはQtのバージョンやスタイルによって挙動が異なる場合があります。

2.2 桁区切り (Group Separator)

大きな数値を表示する際に、桁区切り記号(通常はカンマやスペースなど)を表示することで、読みやすさを向上させることができます。使用される桁区切り記号は、システムのロケール設定に依存します。

  • 桁区切りの表示/非表示を設定: setGroupSeparatorShown(bool shown) メソッドを使用します。

“`python

桁区切りを表示する

self.spin_box.setGroupSeparatorShown(True)
“`

例えば、桁区切りを有効にし、値が10000の場合、ロケールによっては「10,000」のように表示されます。これは特に大きな数値を扱う場合に便利です。

2.3 値のラッピング (Wrapping)

範囲の最小値を超えて減少させた場合、最大値に戻る、あるいは最大値を超えて増加させた場合、最小値に戻るように設定できます。これを値のラッピングと呼びます。

  • ラッピングを有効/無効に設定: setWrapping(bool wrap) メソッドを使用します。

“`python

値のラッピングを有効にする

self.spin_box.setWrapping(True)
“`

ラッピングを有効にすると、例えば範囲が0から100の場合、100から増加させると0に戻り、0から減少させると100に戻ります。これは円形のリストから値を選択するようなシナリオで役立ちます。デフォルトでは無効になっています。

3. 操作性のカスタマイズ

QSpinBoxは、ユーザーの操作に関するいくつかの設定を提供します。

3.1 読み取り専用 (Read-Only)

ユーザーが値を変更できないように、QSpinBoxを読み取り専用にすることができます。値は表示されますが、テキスト編集やスピンボタンの操作は無効になります。

  • 読み取り専用に設定: setReadOnly(bool readOnly) メソッドを使用します。

“`python

読み取り専用にする

self.spin_box.setReadOnly(True)
“`

setReadOnly(False) とすると、編集可能に戻ります。これは、特定の条件下でのみユーザーに値の変更を許可したい場合などに便利です。

3.2 キーボード操作とマウスホイール操作

QSpinBoxは、スピンボタンだけでなく、キーボードやマウスホイールによる操作もサポートしています。

  • キーボード:
    • 上下矢印キー: singleStep で設定されたステップ幅で値を増減させます。
    • PageUp/PageDownキー: デフォルトでは singleStep の10倍のステップ幅で値を増減させます。この倍率は setKeyboardTracking の設定によって影響を受けることがあります(後述のsetKeyboardTrackingの説明で補足)。
  • マウスホイール: QSpinBoxの上にマウスカーソルがある状態でマウスホイールを回転させると、値が singleStep で増減します。

3.3 キーボードトラッキング (Keyboard Tracking)

ユーザーがテキストエディタ部分に値を直接入力している最中に、valueChanged 信号をいつ発行するかを制御できます。

  • setKeyboardTracking(bool enable) メソッドを使用します。

“`python

キーボードトラッキングを無効にする (デフォルトは有効)

self.spin_box.setKeyboardTracking(False)
“`

  • True (デフォルト): ユーザーがキーボードで入力するたびに、潜在的な値が変化するとすぐに valueChanged 信号が発行されます。
  • False: ユーザーがテキストエディタからフォーカスを移動したとき(編集中でなくなったとき)、または Enter キーを押したときにのみ valueChanged 信号が発行されます。

True の場合、入力途中の無効な値でも信号が発行される可能性がありますが、リアルタイムなフィードバックには適しています。False の場合、確定した有効な値でのみ信号が発行されるため、処理がシンプルになることがあります。どちらを選ぶかは、アプリケーションの要件によります。

また、setKeyboardTracking(False) に設定した場合、PageUp/PageDownキーの挙動が変更され、デフォルトの10倍ではなく、単に singleStep だけ変化するようになることがあります。これはQtのバージョンやプラットフォームに依存する可能性があるため、注意が必要です。

4. 関連クラス:QDoubleSpinBoxとQDateTimeEdit

Qtには、QSpinBox以外にも数値や日時を扱う類似のウィジェットがあります。主要なものとしてQDoubleSpinBoxQDateTimeEditが挙げられます。これらはQSpinBoxと多くの共通点を持っていますが、扱うデータの型が異なります。

4.1 QDoubleSpinBox

QDoubleSpinBoxは、浮動小数点数(小数)の入力を扱うためのウィジェットです。基本的な構成要素(テキストエディタとスピンボタン)や、範囲設定、ステップ幅、接頭辞・接尾辞、桁区切り、ラッピング、読み取り専用などの機能はQSpinBoxと共通していますが、以下の点が異なります。

  • 扱うデータ型: int ではなく double または float を扱います。
  • ステップ幅: setSingleStep(double step) メソッドを使用します。
  • 範囲: setMinimum(double min), setMaximum(double max), setRange(double min, double max) メソッドを使用します。
  • 値の取得/設定: value()double を返し、setValue(double value) で設定します。
  • 信号: valueChanged(double d)valueChanged(QString text) があります。
  • 小数点以下の桁数: setDecimals(int prec) メソッドで小数点以下に表示・編集可能な桁数を設定できます。デフォルトは1です。

QDoubleSpinBoxの例:

“`python
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QDoubleSpinBox, QLabel
import sys

class DoubleSpinBoxWindow(QMainWindow):
def init(self):
super().init()

    self.setWindowTitle("QDoubleSpinBox Example")
    self.setGeometry(100, 100, 300, 200)

    layout = QVBoxLayout()

    label = QLabel("浮動小数点数を入力してください:")
    layout.addWidget(label)

    self.double_spin_box = QDoubleSpinBox()
    self.double_spin_box.setRange(0.0, 10.0)
    self.double_spin_box.setSingleStep(0.5)
    self.double_spin_box.setDecimals(2) # 小数点以下2桁まで表示/編集可能
    self.double_spin_box.setValue(3.14)

    layout.addWidget(self.double_spin_box)

    central_widget = QWidget()
    central_widget.setLayout(layout)
    self.setCentralWidget(central_widget)

    self.double_spin_box.valueChanged.connect(self.on_double_value_changed)

def on_double_value_changed(self, new_value):
    print(f"浮動小数点数の値が変化しました: {new_value}")

if name == “main“:
app = QApplication(sys.argv)
window = DoubleSpinBoxWindow()
window.show()
sys.exit(app.exec())
“`

浮動小数点数を扱う必要がある場合は、QSpinBoxではなくQDoubleSpinBoxを選択してください。

4.2 QDateTimeEdit

QDateTimeEditは、日付、時刻、またはその両方を入力するためのウィジェットです。これは直接的なSpinBoxではありませんが、上下ボタンを使って値を増減させる点、範囲を設定できる点など、QSpinBoxと共通のインタフェースを持っています。年、月、日、時、分、秒といった各要素をSpinBoxのように操作できます。

QDateTimeEditは、QDateEdit (日付のみ) と QTimeEdit (時刻のみ) の機能を合わせたものです。

主な機能:

  • 表示フォーマットの設定: setDisplayFormat(str format) メソッドで、表示される日付/時刻の形式をカスタマイズできます (“yyyy/MM/dd HH:mm:ss” など)。
  • 日付/時刻の設定と取得: setDateTime(QDateTime dt), setDate(QDate d), setTime(QTime t)dateTime(), date(), time() メソッドを使用します。
  • 範囲設定: setMinimumDateTime, setMaximumDateTime などで有効な日時範囲を設定できます。
  • 信号: dateTimeChanged(QDateTime dt), dateChanged(QDate d), timeChanged(QTime t) などがあります。

日時入力を扱う場合は、QSpinBoxQDoubleSpinBoxではなく、QDateTimeEdit(またはQDateEdit/QTimeEdit)を使用するのが適切です。

5. QSpinBoxの詳細と応用

5.1 バリデーション(入力検証)

QSpinBoxは、設定された範囲内での整数入力のみを受け付けます。ユーザーがテキストエディタ部分に無効な文字(アルファベットなど)を入力しようとすると、Qtの入力検証メカニズムによって自動的に拒否されます。また、範囲外の数値を入力しても、フォーカスが外れたときなどに自動的に範囲内にクランプされます。

この自動的なバリデーション機能は非常に便利ですが、より複雑な検証ロジック(例えば、偶数のみを受け付ける、特定の数値を除外するなど)が必要な場合は、追加の処理が必要です。これは通常、valueChanged 信号を補足し、入力された値が要件を満たしているかチェックし、満たしていない場合はユーザーに警告したり、値を元に戻したりする方法で行います。

例えば、偶数のみを許可したい場合:

python
def on_value_changed_validate_even(self, new_value):
if new_value % 2 != 0:
print(f"警告: 偶数のみ入力可能です。無効な値: {new_value}")
# 無効な値を元の有効な値に戻す、あるいは修正する
# 最も簡単な方法は、直前の有効な値を保持しておき、無効な入力があった場合に setValue() で戻すことですが、
# これはキーボードトラッキングの設定などによって挙動が複雑になる可能性があります。
# または、setValue(new_value - (new_value % 2)) のように修正することも可能です。
pass # ここでは簡単な例として何もしないか、警告を表示するだけとする

より堅牢なバリデーションを実装するには、QSpinBoxの内部で使われているQAbstractSpinBoxクラスのvalidator()や、QLineEditに設定するQValidatorの概念を理解する必要がありますが、通常QSpinBoxの範囲制限機能で十分な場合が多いです。

5.2 ロケールの影響

QSpinBoxは、数値の表示形式や、桁区切りに使用する文字、小数点記号などを、システムのロケール設定に基づいて自動的に調整します。setLocale(QLocale locale) メソッドを使って、明示的に特定のロケールを設定することも可能です。

“`python
from PySide6.QtCore import QLocale

日本語ロケールを設定 (桁区切りにカンマが使われるなど)

self.spin_box.setLocale(QLocale(QLocale.Japanese))

英語 (米国) ロケールを設定

self.spin_box.setLocale(QLocale(QLocale.English, QLocale.UnitedStates))

“`

特に国際化されたアプリケーションでは、ユーザーの環境に合わせた表示形式を提供するために、ロケールの設定が重要になります。

5.3 スタイルシートによるデザインカスタマイズ

Qtのウィジェットは、CSSライクなスタイルシートを使って外観をカスタマイズできます。QSpinBoxも例外ではありません。背景色、ボーダー、フォント、スピンボタンの外観などを変更できます。

“`python

QSpinBoxの背景色を薄い黄色に設定

self.spin_box.setStyleSheet(“””
QSpinBox {
background-color: #FFFFE0; / lightyellow /
border: 1px solid #A9A9A9; / darkgray /
border-radius: 3px;
padding: 1px 18px 1px 3px; / テキストのパディング。右側のパディングはスピンボタンのスペースを確保 /
}
QSpinBox::up-button {
subcontrol-origin: border;
subcontrol-position: top right; / ボタンの位置 /
width: 16px; / ボタンの幅 /
border-left: 1px solid #A9A9A9;
image: url(up_arrow.png); / カスタム画像を使用する場合 /
}
QSpinBox::down-button {
subcontrol-origin: border;
subcontrol-position: bottom right; / ボタンの位置 /
width: 16px;
border-left: 1px solid #A9A9A9;
image: url(down_arrow.png); / カスタム画像を使用する場合 /
}
QSpinBox::up-arrow { / ボタン内の矢印アイコン /
image: url(:/qt-project.org/styles/commonstyle/images/up_arrow_12.png); / デフォルトの矢印 /
width: 8px;
height: 8px;
}
QSpinBox::down-arrow {
image: url(:/qt-project.org/styles/commonstyle/images/down_arrow_12.png);
width: 8px;
height: 8px;
}
“””)
“`

この例はスタイルシートの機能のごく一部を示しています。QSpinBoxとそのサブコントロール (::up-button, ::down-button, ::up-arrow, ::down-arrow) に対して詳細なスタイルを設定できます。カスタム画像をスピンボタンに使用することも可能です。

5.4 アクセシビリティ

Qtウィジェットは、アクセシビリティ(視覚障害者や身体障害者など、様々なユーザーがアプリケーションを利用しやすくするための配慮)を考慮して設計されています。QSpinBoxも例外ではありません。キーボードナビゲーション(Tabキーでのフォーカス移動、矢印キーでの値変更など)や、スクリーンリーダーによる読み上げに対応しています。特別な設定を行わなくても、基本的なアクセシビリティ機能は提供されます。より高度なアクセシビリティ要件がある場合は、QSpinBoxaccessibleDescriptionなどのプロパティを設定することを検討してください。

6. 実践的な使い方と例

ここでは、QSpinBoxを複数のウィジェットと組み合わせて使用する例や、より実践的なシナリオでの利用法について説明します。

6.1 複数のQSpinBoxを持つダイアログ

アプリケーションの設定ダイアログなどで、複数のパラメータをQSpinBoxで入力させるのはよくあるケースです。

“`python
import sys
from PySide6.QtWidgets import (QApplication, QDialog, QVBoxLayout, QHBoxLayout,
QLabel, QSpinBox, QDialogButtonBox, QGroupBox)
from PySide6.QtCore import Qt

class SettingsDialog(QDialog):
def init(self, parent=None):
super().init(parent)
self.setWindowTitle(“設定”)

    main_layout = QVBoxLayout()

    # 数値設定グループ
    numerical_group = QGroupBox("数値設定")
    numerical_layout = QVBoxLayout()

    # ウィンドウ幅設定
    width_layout = QHBoxLayout()
    width_label = QLabel("ウィンドウ幅:")
    self.width_spinbox = QSpinBox()
    self.width_spinbox.setRange(100, 1920)
    self.width_spinbox.setValue(800)
    width_layout.addWidget(width_label)
    width_layout.addWidget(self.width_spinbox)
    numerical_layout.addLayout(width_layout)

    # ウィンドウ高さ設定
    height_layout = QHBoxLayout()
    height_label = QLabel("ウィンドウ高さ:")
    self.height_spinbox = QSpinBox()
    self.height_spinbox.setRange(100, 1080)
    self.height_spinbox.setValue(600)
    height_layout.addWidget(height_label)
    height_layout.addWidget(self.height_spinbox)
    numerical_layout.addLayout(height_layout)

    # 最大アイテム数設定
    max_items_layout = QHBoxLayout()
    max_items_label = QLabel("最大アイテム数:")
    self.max_items_spinbox = QSpinBox()
    self.max_items_spinbox.setRange(1, 1000)
    self.max_items_spinbox.setSingleStep(10)
    self.max_items_spinbox.setValue(100)
    self.max_items_spinbox.setSuffix(" 個")
    self.max_items_spinbox.setGroupSeparatorShown(True)
    max_items_layout.addWidget(max_items_label)
    max_items_layout.addWidget(self.max_items_spinbox)
    numerical_layout.addLayout(max_items_layout)

    numerical_group.setLayout(numerical_layout)
    main_layout.addWidget(numerical_group)

    # ダイアログボタン
    button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
    button_box.accepted.connect(self.accept)
    button_box.rejected.connect(self.reject)
    main_layout.addWidget(button_box)

    self.setLayout(main_layout)

def get_settings(self):
    return {
        "width": self.width_spinbox.value(),
        "height": self.height_spinbox.value(),
        "max_items": self.max_items_spinbox.value()
    }

メインウィンドウから設定ダイアログを開く例

class MainWindow(QMainWindow):
def init(self):
super().init()
self.setWindowTitle(“設定ダイアログ例”)
self.setGeometry(100, 100, 400, 300)

    layout = QVBoxLayout()
    self.settings_label = QLabel("現在の設定: ")
    layout.addWidget(self.settings_label)

    open_dialog_button = QPushButton("設定を開く")
    open_dialog_button.clicked.connect(self.open_settings_dialog)
    layout.addWidget(open_dialog_button)

    central_widget = QWidget()
    central_widget.setLayout(layout)
    self.setCentralWidget(central_widget)

    # 初期のダミー設定
    self.current_settings = {"width": 800, "height": 600, "max_items": 100}
    self.update_settings_label()

def open_settings_dialog(self):
    dialog = SettingsDialog(self)
    # ダイアログを開く前に現在の設定をSpinBoxにセット
    dialog.width_spinbox.setValue(self.current_settings["width"])
    dialog.height_spinbox.setValue(self.current_settings["height"])
    dialog.max_items_spinbox.setValue(self.current_settings["max_items"])

    if dialog.exec() == QDialog.Accepted:
        self.current_settings = dialog.get_settings()
        self.update_settings_label()
        print("設定が保存されました:", self.current_settings)
    else:
        print("設定は破棄されました")

def update_settings_label(self):
    self.settings_label.setText(f"現在の設定: 幅={self.current_settings['width']}, 高さ={self.current_settings['height']}, 最大アイテム数={self.current_settings['max_items']}")

if name == “main“:
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
``
この例では、3つの
QSpinBoxを含むQDialogを作成し、メインウィンドウからその設定値を読み書きするシミュレーションを行っています。それぞれのQSpinBox`で異なる範囲、ステップ、接尾辞、桁区切りを設定しています。

6.2 QSpinBoxと他のウィジェットの連携

QSpinBoxは、他のウィジェットと連携して使用されることも多いです。例えば、QSliderと連携させて、両方で同じ値を操作できるようにする、といった使い方が考えられます。

QSpinBoxとQSliderはどちらも整数値を扱いますが、UIの性質が異なります。QSpinBoxは正確な数値入力を、QSliderは直感的な範囲指定に適しています。両者を連携させることで、ユーザーは好みの方法で値を操作できるようになります。

連携は、それぞれのvalueChanged信号を、互いのsetValue()スロットに接続することで実現できます。

“`python
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QSpinBox, QSlider, QLabel
from PySide6.QtCore import Qt

class SliderSpinBoxWindow(QMainWindow):
def init(self):
super().init()
self.setWindowTitle(“Slider and SpinBox Sync Example”)
self.setGeometry(100, 100, 300, 200)

    layout = QVBoxLayout()

    label = QLabel("スライダーまたはスピンボックスを操作:")
    layout.addWidget(label)

    # QSpinBoxの設定
    self.spin_box = QSpinBox()
    self.spin_box.setRange(0, 100)
    self.spin_box.setSingleStep(1)
    self.spin_box.setValue(50)
    layout.addWidget(self.spin_box)

    # QSliderの設定
    self.slider = QSlider(Qt.Orientation.Horizontal) # 水平方向のスライダー
    self.slider.setRange(0, 100)
    self.slider.setSingleStep(1)
    self.slider.setValue(50)
    self.slider.setTickPosition(QSlider.TicksBelow) # 目盛りを表示
    self.slider.setTickInterval(10) # 目盛りの間隔
    layout.addWidget(self.slider)

    central_widget = QWidget()
    central_widget.setLayout(layout)
    self.setCentralWidget(central_widget)

    # 信号とスロットの接続
    # SpinBoxの値が変化したらSliderの値を更新
    self.spin_box.valueChanged.connect(self.slider.setValue)

    # Sliderの値が変化したらSpinBoxの値を更新
    self.slider.valueChanged.connect(self.spin_box.setValue)

if name == “main“:
app = QApplication(sys.argv)
window = SliderSpinBoxWindow()
window.show()
sys.exit(app.exec())
``
このコードでは、QSpinBoxとQSliderを作成し、両方の
valueChanged信号を互いのsetValue()`スロットに接続しています。これにより、片方のウィジェットを操作すると、もう片方のウィジェットの値も同期して変化します。

6.3 設定値の永続化

アプリケーションの設定値としてQSpinBoxの値を使用する場合、その値をアプリケーションの終了時に保存し、次回起動時に読み込む必要があります。これはQtのQSettingsクラスを使用するか、あるいは独自の設定ファイル(JSON, XMLなど)を扱うことで実現できます。

QSettingsを使用する場合の概念的な流れは以下のようになります。

  1. 保存: アプリケーション終了時(または設定ダイアログの「OK」押下時)に、QSpinBoxのvalue()を取得し、QSettingsオブジェクトを使ってキーと値のペアとして保存します。
    python
    # 例: settingsはQSettingsオブジェクト
    settings.setValue("window/width", self.width_spinbox.value())
    settings.setValue("window/height", self.height_spinbox.value())
    settings.setValue("general/max_items", self.max_items_spinbox.value())
  2. 読み込み: アプリケーション起動時(または設定ダイアログ表示時)に、QSettingsオブジェクトから保存された値を読み込み、QSpinBoxのsetValue()で設定します。
    “`python
    # 例: settingsはQSettingsオブジェクト
    # 存在しない場合はデフォルト値を使用
    width = settings.value(“window/width”, 800, type=int)
    height = settings.value(“window/height”, 600, type=int)
    max_items = settings.value(“general/max_items”, 100, type=int)

    self.width_spinbox.setValue(width)
    self.height_spinbox.setValue(height)
    self.max_items_spinbox.setValue(max_items)
    “`

これにより、ユーザーが設定した値をアプリケーションのセッションを超えて維持することができます。

7. QSpinBoxの限界と代替手段

QSpinBoxは多くの数値入力シナリオに適していますが、すべての状況に最適なわけではありません。その限界を理解し、必要に応じて代替手段を検討することも重要です。

7.1 QSpinBoxの限界

  • 整数値のみ: QSpinBoxは整数値に特化しています。小数点以下の値が必要な場合は、QDoubleSpinBoxを使用する必要があります。
  • 連続する数値の範囲: 基本的には、定義された範囲内の連続する整数値を扱います。非連続な値(例: 10, 20, 30, 50, 100…)のリストから選択させるようなケースには不向きです。
  • 非常に広い範囲: 極端に広い範囲(例: -2,000,000,000 から 2,000,000,000)を扱う場合、スピンボタンでの操作は実用的ではありません。このような場合は、直接入力が可能なテキストフィールドの方が適しています。
  • カスタムフォーマット: 接頭辞、接尾辞、桁区切り以外の複雑なフォーマット(例: 特定の単位の変換、特別な記号の挿入など)を表示・編集させることは困難です。
  • 非数値入力との組み合わせ: 数値と一緒に非数値の情報を入力させるようなケース(例: 部屋番号 “Apt 101″)には使用できません。

7.2 代替手段

上記のようなQSpinBoxの限界に直面した場合、以下のウィジェットや手法を検討してください。

  • QDoubleSpinBox: 浮動小数点数が必要な場合。
  • QLineEdit + QValidator: 自由な形式のテキスト入力を受け付け、QValidatorQIntValidator, QDoubleValidator, QRegExpValidatorなど)を使って入力内容を検証する方法です。これにより、より柔軟な入力形式や複雑なバリデーションルールに対応できます。ただし、スピンボタンによる段階的な値変更機能は提供されません。
  • QComboBox: あらかじめ定義された非連続な値のリストからユーザーに選択させる場合に適しています。
  • カスタムウィジェット: 非常に特殊な数値入力やフォーマットが必要な場合は、既存のウィジェットを組み合わせたり、QAbstractSpinBoxQLineEditを継承して独自のウィジェットを作成したりすることも可能です。

QSpinBoxは、適切な範囲内の整数値をユーザーが簡単に、かつ間違いなく入力できるようにするための優れたウィジェットです。多くの一般的な設定や数量入力の場面で活躍します。

8. まとめ

この記事では、QtフレームワークのQSpinBoxウィジェットについて、その基本的な使い方から、表示・操作のカスタマイズ、関連クラスとの比較、実践的な応用例、そして限界と代替手段まで、詳細に解説しました。

QSpinBoxは、以下の特徴を持つ、整数入力に特化した強力なウィジェットです。

  • テキストエディタとスピンボタンによる直感的・正確な入力
  • 設定可能な値の範囲(最小値、最大値)
  • 設定可能な値の増減ステップ幅
  • 接頭辞・接尾辞による表示のカスタマイズ
  • 桁区切りによる視認性の向上
  • 値のラッピング機能
  • valueChanged信号による値の変化の検知
  • キーボードやマウスホイールによる操作への対応
  • 読み取り専用設定

これらの機能を組み合わせることで、様々なシナリオに適した数値入力UIを構築できます。特に、定義された範囲内の整数値をユーザーに入力させたい場面では、QSpinBoxは最も手軽で効果的な選択肢の一つです。

また、浮動小数点数を扱うためのQDoubleSpinBoxや、日時を扱うためのQDateTimeEditについても触れ、それぞれの使い分けを説明しました。

GUIアプリケーション開発において、ユーザーフレンドリーな数値入力インターフェースを提供することは、アプリケーションの品質を高める上で非常に重要です。QSpinBoxはそのための強力なツールの一つであり、この記事で解説した知識が、あなたのQtアプリケーション開発の一助となれば幸いです。

ぜひ、実際にコードを書いてQSpinBoxを使ってみてください。様々なプロパティやメソッドを試しながら、その挙動を理解することが、Qtウィジェットを使いこなすための最良の方法です。

付録:QSpinBoxの主なプロパティ、メソッド、シグナル一覧

種類 名前 型 (Python) 型 (C++) 説明
プロパティ value int int 現在の値
minimum int int 最小値
maximum int int 最大値
singleStep int int スピンボタンまたは矢印キーでのステップ幅
prefix str QString 値の前に表示される文字列
suffix str QString 値の後に表示される文字列
groupSeparatorShown bool bool 桁区切りを表示するかどうか
readOnly bool bool 読み取り専用かどうか
wrapping bool bool 値のラッピングを有効にするかどうか
keyboardTracking bool bool キーボード入力中にvalueChanged信号を発行するかどうか
specialValueText str QString 最小値(または他の特定の値)に設定されたときに表示するテキスト
メソッド setValue(int value) 値を設定する
setMinimum(int min) 最小値を設定する
setMaximum(int max) 最大値を設定する
setRange(int min, int max) 範囲をまとめて設定する
setSingleStep(int step) ステップ幅を設定する
setPrefix(str prefix) 接頭辞を設定する
setSuffix(str suffix) 接尾辞を設定する
setGroupSeparatorShown(bool shown) 桁区切りの表示/非表示を設定する
setReadOnly(bool readOnly) 読み取り専用を設定する
setWrapping(bool wrap) ラッピングを有効/無効に設定する
setKeyboardTracking(bool enable) キーボードトラッキングを設定する
setSpecialValueText(str text) 特殊値テキストを設定する
text() str QString 現在の表示テキスト(接頭辞、接尾辞などを含む)を取得する
cleanText() str QString 表示テキストから接頭辞、接尾辞などを除いた部分を取得する(通常は数値の文字列)
stepBy(int steps) 指定したステップ数だけ値を変化させる(正の値で増加、負の値で減少)
シグナル valueChanged(int i) 値が整数として変化したときに発行される
valueChanged(QString text) 値が表示テキストとして変化したときに発行される

この表はQSpinBoxの主要な要素をまとめたものです。Qtの公式ドキュメントには、より詳細な情報や全てのメソッド、シグナルが記載されていますので、必要に応じて参照してください。


約5000語の詳細な解説記事として、Qt SpinBoxの機能、使い方、関連情報などを網羅的に説明しました。コード例を豊富に含め、概念の理解を助けるように努めました。

この内容が、あなたのQtアプリケーション開発に役立つことを願っています。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール