スライダーの例

スライダーの例では、Qt で利用可能な様々なタイプのスライダーの使い方を示しています:QSlider QScrollBarQDial

Qt には、3 種類のスライダーのようなウィジェットがあります:QSlider QScrollBarQDial です。これらのウィジェットは、QAbstractSlider からほとんどの機能を継承しており、ルック&フィールの違いだけなので、理論的にはアプリケーション内で置き換えることができます。この例では、それらの見た目、動作、プロパティによる動作と見た目の操作方法を示します。

また、2つ以上のウィジェットの動作を同期させるためにシグナルとスロットを使用する方法と、レスポンシブ・レイアウトを実装するためにresizeEvent() をオーバーライドする方法も示します。

スライダーの例のスクリーンショット

Slidersのサンプルは、2つのクラスで構成されています:

  • SlidersGroup はカスタムウィジェットです。 と と を組み合わせています。QSlider QScrollBar QDial
  • Window は と SlidersGroup を組み合わせたメイン・ウィジェットです。 には、スライダーのようなウィジェットの動作を制御するウィジェットがいくつか含まれています。QGroupBox QGroupBox

最初にWindow クラスを確認し、次にSlidersGroup クラスを見ていきます。

ウィンドウ・クラスの定義

class Window : public QWidget
{
    Q_OBJECT

public:
    Window(QWidget *parent = nullptr);

private:
    void createControls(const QString &title);
    void resizeEvent(QResizeEvent *e);

    SlidersGroup *slidersGroup;

    QGroupBox *controlsGroup;
    QLabel *minimumLabel;
    QLabel *maximumLabel;
    QLabel *valueLabel;
    QCheckBox *invertedAppearance;
    QCheckBox *invertedKeyBindings;
    QSpinBox *minimumSpinBox;
    QSpinBox *maximumSpinBox;
    QSpinBox *valueSpinBox;
    QBoxLayout *layout;
};

Window クラスはQWidget を継承しています。このクラスはスライダー・ウィジェットを表示し、ユーザーがその最小値、最大値、現在値を設定し、外観、キー・バインディング、向きをカスタマイズできるようにします。これらの制御メカニズムを提供するウィジェットを作成し、それらをスライダーウィジェットに接続するために、プライベートなcreateControls() 関数を使用します。

ウィンドウ クラスの実装

Window::Window(QWidget *parent)
    : QWidget(parent)
{
    slidersGroup = new SlidersGroup(tr("Sliders"));

    createControls(tr("Controls"));

コンストラクタでは、まずスライダーウィジェットを表示するSlidersGroup ウィジェットを作成します。createControls() で制御ウィジェットを作成し、それらをスライダーに接続します。

    layout = new QBoxLayout(QBoxLayout::LeftToRight);
    layout->addWidget(controlsGroup);
    layout->addWidget(slidersGroup);
    setLayout(layout);

    minimumSpinBox->setValue(0);
    maximumSpinBox->setValue(20);
    valueSpinBox->setValue(5);

    setWindowTitle(tr("Sliders"));
}

最小値、最大値、現在値を初期化する前に、制御ウィジェットのグループとスライダーを水平レイアウトにします。現在値の初期化は、valueSpinBoxSlidersGroup ウィジェットの間に作った接続を通して、スライダーウィジェットに伝わります。最小値と最大値は、createControls() で作成した接続を通じて伝搬されます。

void Window::createControls(const QString &title)
{
    controlsGroup = new QGroupBox(title);

    minimumLabel = new QLabel(tr("Minimum value:"));
    maximumLabel = new QLabel(tr("Maximum value:"));
    valueLabel = new QLabel(tr("Current value:"));

    invertedAppearance = new QCheckBox(tr("Inverted appearance"));
    invertedKeyBindings = new QCheckBox(tr("Inverted key bindings"));

privatecreateControls() 関数では、QGroupBox (controlsGroup) にコントロール・ウィジェットを表示させます。グループ・ボックスは、フレーム、タイトル、キーボード・ショートカットを提供することができ、それ自身の中に他のさまざまなウィジェットを表示します。コントロール・ウィジェットのグループは、2つのチェック・ボックスと、ラベル付きの3つのスピン・ボックスで構成されています。

ラベルを作成した後、2つのチェックボックスを作成します。チェックボックスは、通常、有効または無効にできるアプリケーションの機能を表すために使用されます。invertedAppearance を有効にすると、スライダーの値が反転します。下の表は、異なるスライダーのようなウィジェットの外観を示しています:

QSliderQScrollBarQDial
通常反転通常反転通常倒立
Qt::Horizontal左から右右から左左から右右から左時計回り反時計回り
Qt::Vertical下から上へ上から下へ上から下へ下から上時計回り反時計回り

垂直QSlider の外観を反転させることは一般的です。例えば、音量をコントロールする垂直スライダーは、通常、下から上に移動します(反転しない外観)。一方、スクリーン上のオブジェクトの位置をコントロールする垂直スライダーは、スクリーン座標が上から下に移動するため、上から下に移動するかもしれません。

invertedKeyBindings オプションを有効にすると(QAbstractSlider::invertedControls プロパティに対応)、スライダーのホイールとキーイベントは反転します。通常のキーバインドでは、マウスホイールを「上」にスクロールしたり、page upなどのキーを使用すると、スライダーの現在値が最大値に向かって増加します。逆の場合、同じホイールやキーイベントはスライダーの最小値に向かって値を移動させます。これは、スライダーの外観が反転している場合に便利です:ユーザーによっては、キーが値に対して同じように動作することを期待するかもしれませんし、他のユーザーはPageUp がスクリーン上で "up" を意味することを期待するかもしれません。

水平・垂直スクロールバーの場合、デフォルトではキーバインディングが逆になっていることに注意してください。PageDown は現在の値を増加させ、PageUp は減少させます。

    minimumSpinBox = new QSpinBox;
    minimumSpinBox->setRange(-100, 100);
    minimumSpinBox->setSingleStep(1);

    maximumSpinBox = new QSpinBox;
    maximumSpinBox->setRange(-100, 100);
    maximumSpinBox->setSingleStep(1);

    valueSpinBox = new QSpinBox;
    valueSpinBox->setRange(-100, 100);
    valueSpinBox->setSingleStep(1);

次にスピンボックスを作成します。QSpinBox 、ユーザーは上下のボタンをクリックするか、キーボードのUpDown キーを押して値を選択し、現在表示されている値を変更することができます。ユーザーは手動で値を入力することもできます。スピンボックスは、QSliderQScrollBarQDial ウィジェットの最小値、最大値、現在値を制御します。

    connect(slidersGroup, &SlidersGroup::valueChanged,
            valueSpinBox, &QSpinBox::setValue);
    connect(valueSpinBox, &QSpinBox::valueChanged,
            slidersGroup, &SlidersGroup::setValue);
    connect(minimumSpinBox, &QSpinBox::valueChanged,
            slidersGroup, &SlidersGroup::setMinimum);
    connect(maximumSpinBox, &QSpinBox::valueChanged,
            slidersGroup, &SlidersGroup::setMaximum);
    connect(invertedAppearance, &QCheckBox::toggled,
            slidersGroup, &SlidersGroup::invertAppearance);
    connect(invertedKeyBindings, &QCheckBox::toggled,
            slidersGroup, &SlidersGroup::invertKeyBindings);

    QGridLayout *controlsLayout = new QGridLayout;
    controlsLayout->addWidget(minimumLabel, 0, 0);
    controlsLayout->addWidget(maximumLabel, 1, 0);
    controlsLayout->addWidget(valueLabel, 2, 0);
    controlsLayout->addWidget(minimumSpinBox, 0, 1);
    controlsLayout->addWidget(maximumSpinBox, 1, 1);
    controlsLayout->addWidget(valueSpinBox, 2, 1);
    controlsLayout->addWidget(invertedAppearance, 0, 2);
    controlsLayout->addWidget(invertedKeyBindings, 1, 2);
    controlsGroup->setLayout(controlsLayout);

}

そして、slidersGroupvalueSpinBox を互いに接続し、スライダー・ウィジェットとコントロール・ウィジェットのどちらかの現在値が変化したときに同期して動作するようにします。valueChanged() シグナルは、新しい値を引数として発信されます。setValue() スロットは、ウィジェットの現在値を新しい値に設定し、新しい値が古い値と異なる場合にvalueChanged() を発信します。

コントロール・ウィジェットとスライダー・ウィジェットの動作は、シグナルとスロットによって同期されます。各コントロール・ウィジェットをスライダー・ウィジェットの水平グループと垂直グループの両方に接続する。また、orientationComboQStackedWidget に接続し、正しい「ページ」が表示されるようにします。最後に、controlsGroup グループボックス内のQGridLayout にコントロール・ウィジェットをレイアウトします。

void Window::resizeEvent(QResizeEvent *)
{
    if (width() == 0 || height() == 0)
        return;

    const double aspectRatio = double(width()) / double(height());

    if (aspectRatio < 1.0) {
        layout->setDirection(QBoxLayout::TopToBottom);
        slidersGroup->setOrientation(Qt::Horizontal);
    } else if (aspectRatio > 1.0) {
        layout->setDirection(QBoxLayout::LeftToRight);
        slidersGroup->setOrientation(Qt::Vertical);
    }
}

最後に、QWidget から resizeEvent() をオーバーライドします。ゼロで除算されないようにし、ウィジェットの縦横比を計算します。ウィンドウが縦長の場合は、コントロール・ウィジェットのグループとスライダーを縦に配置するようにレイアウトを設定し、スライダーを横長に配置します。ウィンドウが横長フォーマットの場合は、スライダーと制御ウィジェットを横に並べて表示するようにレイアウトを変更し、スライダーに縦方向を与えます。

SlidersGroupクラスの定義

class SlidersGroup : public QGroupBox
{
    Q_OBJECT

public:
    SlidersGroup(const QString &title, QWidget *parent = nullptr);

signals:
    void valueChanged(int value);

public slots:
    void setValue(int value);
    void setMinimum(int value);
    void setMaximum(int value);
    void invertAppearance(bool invert);
    void invertKeyBindings(bool invert);
    void setOrientation(Qt::Orientation orientation);

private:
    QSlider *slider;
    QScrollBar *scrollBar;
    QDial *dial;
    QBoxLayout *slidersLayout;
};

SlidersGroup クラスはQGroupBox を継承しています。フレームとタイトルを提供し、QSliderQScrollBarQDial を含んでいます。

valueChanged() シグナルと、QAbstractSliderQSpinBox のものと同等の機能を持つパブリックsetValue() スロットを提供します。さらに、最小値と最大値を設定し、スライダーウィジェットの外観とキーバインディングを反転させ、向きを設定するために、いくつかのパブリックスロットを実装します。

SlidersGroup クラスの実装

SlidersGroup::SlidersGroup(const QString &title, QWidget *parent)
    : QGroupBox(title, parent)
{
    slider = new QSlider;
    slider->setFocusPolicy(Qt::StrongFocus);
    slider->setTickPosition(QSlider::TicksBothSides);
    slider->setTickInterval(10);
    slider->setSingleStep(1);

    scrollBar = new QScrollBar;
    scrollBar->setFocusPolicy(Qt::StrongFocus);

    dial = new QDial;
    dial->setFocusPolicy(Qt::StrongFocus);

最初に、適切なプロパティを持つスライダーのようなウィジェットを作成します。特に、各ウィジェットのフォーカス・ポリシーを設定します。Qt::FocusPolicy は列挙型で、キーボード・フォーカスの取得に関してウィジェットが持つことができるさまざまなポリシーを定義します。Qt::StrongFocus ポリシーは、ウィジェットがタブとクリックの両方でフォーカスを受け付けることを意味します。

    connect(slider, &QSlider::valueChanged, scrollBar, &QScrollBar::setValue);
    connect(scrollBar, &QScrollBar::valueChanged, dial, &QDial::setValue);
    connect(dial, &QDial::valueChanged, slider, &QSlider::setValue);
    connect(dial, &QDial::valueChanged, this, &SlidersGroup::valueChanged);

次に、ウィジェット同士を接続して、ウィジェットの現在の値が変更されても同期されるようにします。

dial'のvalueChanged() シグナルをSlidersGroup'のvalueChanged() シグナルに接続し、変更された値をアプリケーショ ンの他のウィジェット(つまりコントロール・ウィジェット)に通知します。

    slidersLayout = new QBoxLayout(QBoxLayout::LeftToRight);
    slidersLayout->addWidget(slider);
    slidersLayout->addWidget(scrollBar);
    slidersLayout->addWidget(dial);
    setLayout(slidersLayout);
}

最後に、グループボックス内のスライダーウィジェットのレイアウトを作成します。まず、スライダを水平に配置します。

void SlidersGroup::setValue(int value)
{
    slider->setValue(value);
}

setValue() スロットは、QSlider の値を設定します。QScrollBarQDial ウィジェットでsetValue() を明示的に呼び出す必要はありません。QSlider は、値が変更されるとvalueChanged() シグナルを発信し、ドミノ効果をトリガーするからです。

void SlidersGroup::setMinimum(int value)
{
    slider->setMinimum(value);
    scrollBar->setMinimum(value);
    dial->setMinimum(value);
}

void SlidersGroup::setMaximum(int value)
{
    slider->setMaximum(value);
    scrollBar->setMaximum(value);
    dial->setMaximum(value);
}

setMinimum()setMaximum() スロットは、Window クラスがQSliderQScrollBarQDial ウィジェットの範囲を設定するために使用します。

void SlidersGroup::invertAppearance(bool invert)
{
    slider->setInvertedAppearance(invert);
    scrollBar->setInvertedAppearance(invert);
    dial->setInvertedAppearance(invert);
}

void SlidersGroup::invertKeyBindings(bool invert)
{
    slider->setInvertedControls(invert);
    scrollBar->setInvertedControls(invert);
    dial->setInvertedControls(invert);
}

invertAppearance()invertKeyBindings() スロットは、子ウィジェットのinvertedAppearanceinvertedControls プロパティを制御します。

void SlidersGroup::setOrientation(Qt::Orientation orientation)
{
    slidersLayout->setDirection(orientation == Qt::Horizontal
                                ? QBoxLayout::TopToBottom
                                : QBoxLayout::LeftToRight);
    scrollBar->setOrientation(orientation);
    slider->setOrientation(orientation);
}

setOrientation()スロットは、レイアウトの方向とスライダの向きを制御します。水平グループでは、スライダは水平方向に配置されます。vertical groupでは、スライダーは垂直方向に配置され、互いの横に並べられます。

プロジェクト例 @ code.qt.io

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。