Sliders Beispiel

Das Sliders-Beispiel zeigt, wie man die verschiedenen Arten von Schiebereglern, die in Qt verfügbar sind, verwendet: QSlider, QScrollBar und QDial.

Qt bietet drei Arten von Slider-ähnlichen Widgets: QSlider, QScrollBar und QDial. Sie alle erben den größten Teil ihrer Funktionalität von QAbstractSlider und können sich theoretisch in einer Anwendung gegenseitig ersetzen, da die Unterschiede nur das Aussehen und die Bedienung betreffen. Dieses Beispiel zeigt, wie sie aussehen, wie sie funktionieren und wie ihr Verhalten und ihr Aussehen durch ihre Eigenschaften beeinflusst werden können.

Das Beispiel zeigt auch, wie Signale und Slots verwendet werden können, um das Verhalten von zwei oder mehr Widgets zu synchronisieren, und wie man resizeEvent() außer Kraft setzt, um ein responsives Layout zu implementieren.

Screenshot des Sliders-Beispiels

Das Sliders-Beispiel besteht aus zwei Klassen:

  • SlidersGroup ist ein benutzerdefiniertes Widget. Es kombiniert ein QSlider, ein QScrollBar und ein QDial.
  • Window ist das Hauptwidget, das ein QGroupBox und eine SlidersGroup kombiniert. Die Klasse QGroupBox enthält mehrere Widgets, die das Verhalten der schiebereglerähnlichen Widgets steuern.

Zunächst werden wir die Klasse Window und dann die Klasse SlidersGroup betrachten.

Definition der Fensterklasse

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;
};

Die Klasse Window erbt von QWidget. Sie zeigt die Schieberegler-Widgets an und ermöglicht es dem Benutzer, ihre Minimal-, Maximal- und aktuellen Werte einzustellen und ihr Aussehen, ihre Tastenbelegung und Ausrichtung anzupassen. Wir verwenden eine private Funktion createControls(), um die Widgets zu erstellen, die diese Steuerungsmechanismen bereitstellen, und um sie mit den Schieberegler-Widgets zu verbinden.

Implementierung der Fensterklasse

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

    createControls(tr("Controls"));

Im Konstruktor erstellen wir zunächst das SlidersGroup Widget, das die Schieberegler-Widgets anzeigt. Mit createControls() erstellen wir die Steuerungswidgets und verbinden diese mit den Schiebereglern.

    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"));
}

Wir ordnen die Gruppen von Steuerungswidgets und die Schieberegler in einem horizontalen Layout an, bevor wir die Minimal-, Maximal- und aktuellen Werte initialisieren. Die Initialisierung des aktuellen Werts wird über die Verbindung zwischen valueSpinBox und den SlidersGroup Widgets an die Schieberegler-Widgets weitergegeben. Die Minimal- und Maximalwerte werden über die Verbindungen weitergegeben, die wir mit createControls() erstellt haben.

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"));

In der privaten Funktion createControls() lassen wir eine QGroupBox (controlsGroup) die Kontroll-Widgets anzeigen. Ein Gruppenrahmen kann einen Rahmen, einen Titel und eine Tastenkombination bereitstellen und zeigt verschiedene andere Widgets in sich selbst an. Die Gruppe der Kontroll-Widgets besteht aus zwei Kontrollkästchen und drei Drehkästen mit Beschriftungen.

Nachdem wir die Beschriftungen erstellt haben, erstellen wir die beiden Kontrollkästchen. Kontrollkästchen werden normalerweise verwendet, um Funktionen in einer Anwendung darzustellen, die aktiviert oder deaktiviert werden können. Wenn invertedAppearance aktiviert ist, werden die Schiebereglerwerte invertiert. Die folgende Tabelle zeigt das Aussehen der verschiedenen Schieberegler-ähnlichen Widgets:

QSliderQScrollBarQDial
NormalUmgekehrtNormalInvertiertNormalUmgekehrt
Qt::HorizontalLinks nach rechtsRechts nach linksLinks nach rechtsRechts nach linksIm UhrzeigersinnGegen den Uhrzeigersinn
Qt::VerticalUnten nach obenOben nach untenOben nach untenUnten nach obenIm UhrzeigersinnGegen den Uhrzeigersinn

Es ist üblich, das Erscheinungsbild eines vertikalen QSlider zu invertieren. Ein vertikaler Schieberegler, der z. B. die Lautstärke steuert, läuft normalerweise von unten nach oben (das nicht invertierte Erscheinungsbild), während ein vertikaler Schieberegler, der die Position eines Objekts auf dem Bildschirm steuert, von oben nach unten laufen kann, da die Bildschirmkoordinaten von oben nach unten laufen.

Wenn die Option invertedKeyBindings aktiviert ist (entsprechend der Eigenschaft QAbstractSlider::invertedControls ), werden die Rad- und Tastenereignisse des Schiebereglers invertiert. Die normalen Tastenbelegungen bedeuten, dass das Scrollen mit dem Mausrad nach oben oder die Verwendung von Tasten wie "Seite nach oben" den aktuellen Wert des Schiebereglers in Richtung seines Maximums erhöht. In der umgekehrten Reihenfolge verschieben dieselben Mausrad- und Tastenereignisse den Wert in Richtung des Minimums des Schiebereglers. Dies kann nützlich sein, wenn das Aussehen eines Schiebereglers invertiert ist: Einige Benutzer erwarten vielleicht, dass die Tasten immer noch auf die gleiche Weise auf den Wert wirken, während andere erwarten, dass PageUp auf dem Bildschirm "nach oben" bedeutet.

Beachten Sie, dass bei horizontalen und vertikalen Bildlaufleisten die Tastenbelegung standardmäßig invertiert ist: PageDown erhöht den aktuellen Wert und PageUp verringert ihn.

    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);

Dann erstellen wir die Drehfelder. QSpinBox ermöglicht es dem Benutzer, einen Wert auszuwählen, indem er auf die Auf- und Ab-Tasten klickt oder die Tasten Up und Down auf der Tastatur drückt, um den aktuell angezeigten Wert zu ändern. Der Benutzer kann den Wert auch manuell eintippen. Die Drehfelder steuern die Mindest-, Höchst- und aktuellen Werte für die Widgets QSlider, QScrollBar und QDial.

    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);

}

Dann verbinden wir slidersGroup und valueSpinBox miteinander, so dass sich die Schieberegler-Widgets und das Kontroll-Widget synchron verhalten, wenn sich der aktuelle Wert eines von ihnen ändert. Das Signal valueChanged() wird mit dem neuen Wert als Argument ausgesendet. Der Slot setValue() setzt den aktuellen Wert des Widgets auf den neuen Wert und gibt das Signal valueChanged() aus, wenn sich der neue Wert vom alten Wert unterscheidet.

Wir synchronisieren das Verhalten der Kontroll-Widgets und der Schieberegler-Widgets durch ihre Signale und Slots. Wir verbinden jedes Kontroll-Widget sowohl mit der horizontalen als auch mit der vertikalen Gruppe von Schieberegler-Widgets. Außerdem verbinden wir orientationCombo mit der QStackedWidget, damit die richtige "Seite" angezeigt wird. Schließlich ordnen wir die Kontroll-Widgets in einem QGridLayout innerhalb des controlsGroup Gruppenrahmens an.

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);
    }
}

Schließlich überschreiben wir resizeEvent() von QWidget. Wir schützen uns davor, durch Null zu teilen, und berechnen ansonsten das Seitenverhältnis des Widgets. Wenn das Fenster ein Hochformat hat, stellen wir das Layout so ein, dass die Gruppen von Kontroll-Widgets und Schiebereglern vertikal angeordnet sind, und wir geben den Schiebereglern eine horizontale Ausrichtung. Wenn das Fenster ein Querformat hat, wird das Layout so geändert, dass die Schieberegler und Steuerungs-Widgets nebeneinander angezeigt werden und die Schieberegler vertikal ausgerichtet sind.

Definition der Klasse 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;
};

Die Klasse SlidersGroup erbt von QGroupBox. Sie stellt einen Rahmen und einen Titel bereit und enthält ein QSlider, ein QScrollBar und ein QDial.

Wir stellen ein valueChanged() -Signal und einen öffentlichen setValue() -Slot mit der gleichen Funktionalität wie in QAbstractSlider und QSpinBox zur Verfügung. Darüber hinaus implementieren wir mehrere andere öffentliche Slots, um den minimalen und maximalen Wert festzulegen, das Aussehen der Schieberegler-Widgets zu invertieren sowie die Tastenbelegung und die Ausrichtung festzulegen.

Implementierung der Klasse 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);

Zunächst erstellen wir die schiebereglerähnlichen Widgets mit den entsprechenden Eigenschaften. Insbesondere legen wir die Fokus-Policy für jedes Widget fest. Qt::FocusPolicy ist ein Enum-Typ, der die verschiedenen Policies definiert, die ein Widget in Bezug auf den Erwerb des Tastaturfokus haben kann. Die Richtlinie Qt::StrongFocus bedeutet, dass das Widget den Fokus sowohl durch Tabulieren als auch durch Klicken erhält.

    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);

Dann verbinden wir die Widgets miteinander, so dass sie synchronisiert bleiben, wenn sich der aktuelle Wert eines der Widgets ändert.

Wir verbinden das Signal valueChanged() von dial mit dem Signal valueChanged() von SlidersGroup, um die anderen Widgets in der Anwendung (d. h. die Kontroll-Widgets) über den geänderten Wert zu informieren.

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

Schließlich erstellen wir das Layout für die Schieberegler-Widgets innerhalb des Gruppenrahmens. Wir beginnen mit einer horizontalen Anordnung der Schieberegler.

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

Der Slot setValue() setzt den Wert des QSlider. Wir brauchen setValue() nicht explizit auf den Widgets QScrollBar und QDial aufzurufen, da QSlider das Signal valueChanged() aussendet, wenn sich sein Wert ändert, und damit einen Dominoeffekt auslöst.

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);
}

Die Slots setMinimum() und setMaximum() werden von der Klasse Window verwendet, um den Bereich der Widgets QSlider, QScrollBar und QDial festzulegen.

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);
}

Die Slots invertAppearance() und invertKeyBindings() steuern die Eigenschaften der untergeordneten Widgets invertedAppearance und invertedControls.

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

Der Slot setOrientation() steuert die Richtung des Layouts und die Ausrichtung der Schieberegler. In einer horizontalen Gruppe haben die Schieberegler eine horizontale Ausrichtung und sind übereinander angeordnet. Bei einer vertikalen Gruppe haben die Schieberegler eine vertikale Ausrichtung und werden nebeneinander angeordnet.

Beispielprojekt @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.