Ich versuche, ein Element zu verwenden, das dem Android Switches in Qt entspricht. Ich habe einen ToggleSwitch in QML gefunden, aber nichts in den C++ Qt-Bibliotheken. Fehle ich gerade etwas oder muss ich dieses Widget selbst neu implementieren?Kippschalter in Qt
Antwort
@ Piccys Vorschlag ist, was ich für einen solchen Kippschalter zuvor getan habe. Mit ein paar Verbesserungen tho.
Wir mussten das Verhalten ähnlich den iOS-Ein/Aus-Schalter emulieren. Das bedeutet, dass Sie eine schrittweise Bewegung benötigen, die Sie nicht haben werden, wenn der Schieberegler ohne externe Animationen 0-1 beträgt.
Daher wurde der Wertebereich für den Schieberegler so eingestellt, dass er der maximalen Breite des Schiebereglers entspricht.
Schließen Sie dann das freigegebene Slider-Signal an und prüfen Sie, ob der Wert weniger als die Hälfte des Maximums beträgt. Ist dies der Fall, stellen Sie den Schieberegler auf 0 oder den Schieberegler auf max.
Dadurch erhalten Sie einen guten Drag-Effekt und Clip auf Extreme, wenn Sie die Maustaste loslassen.
Wenn Sie möchten, dass der Schieberegler ohne Klicken auf die andere Seite umschaltet, verbinden Sie das veränderte Signal des Schiebereglers und prüfen Sie, ob der neue Wert näher an beiden Extremwerten liegt und setzen Sie den Schieberegler auf nicht in seinem heruntergesetzten Zustand. Ändern Sie den Schiebereglerwert nicht, wenn der Schieberegler nicht gedrückt ist, da Sie dann möglicherweise die vorherige Ziehbewegung unterbrechen.
Nun, Sie müssen QCheckBox verwenden. Es ist kein Toggle Switch, aber es macht dasselbe. Wenn Sie wirklich unterschiedliche visuelle möchten, müssen Sie benutzerdefinierte erstellen müssen Widget
Siehe auch QRadioButton und QPushButton mit checkable und einige Stil-Blatt oder benutzerdefinierte Zeichnung kann wie „Ein/Aus-Schalter Toggle“
Davita gemacht werden ist richtig in his answer, wo es Checkboxen betrifft. Wenn Sie nach etwas suchen, das dem dritten Beispiel ähnlich ist (die Ein/Aus-Schalter), können Sie einfach zwei QPushButton s dafür verwenden und sie auf checkable setzen. Machen Sie sie gleichzeitig autoexclusive, und Sie sollten gut gehen.
Mit ein wenig visuellen Styling using a stylesheet sollten Sie in der Lage sein, nahe zu kommen, wenn nicht gerade auf.
Würden Sie sagen, dass Sie zwei PushButtons nebeneinander anordnen und das Modifizieren des Stylesheets eleganter sein würde als das Einbringen des QML-Objekts? Ich versuche zu sehen, was der beste Weg wäre, um das gleiche Aussehen und Verhalten des Toggle Switch zu erhalten. – ElCraneo
Eleganter könnte ich dir wirklich nicht sagen. Ich habe nicht viel Erfahrung mit dem QML-Teil von Qt. Die QPushbutton-Lösung sollte jedoch wirklich trivial sein, also wäre es mein Weg zu gehen. Aber das basiert nur auf meiner Erfahrung mit Qt (der C++ Seite) und dem Mangel an Erfahrung mit QML. – Bart
Von einem solchen Schalter könnte man einen animierten Übergang erwarten, den zwei QPushButtons nicht bieten. (Stattdessen bringen sie ihre eigenen mit, was in diesem Zusammenhang verwirrend wäre) –
Sie könnten dies auch mit einem QSlider-Steuerelement in einer horizontalen Ausrichtung tun, die einen Bereich von 0 bis 1 hat. Sie möchten wahrscheinlich die maximale Breite auf etwa 50 einstellen, damit es sich nicht über die Breite des Dialogs. Sie können es dann mit einem Stylesheet optimieren, um das Aussehen zu verbessern, oder es unterklassifizieren und die Steuerelemente selbst zeichnen. Es braucht nicht zu viel Code, um es gut aussehen zu lassen.
Ich weiß, dass dieser Thread alt ist, aber ich habe ziemlich mit diesem speziellen Problem gekämpft, obwohl ich einen sehr guten Hinweis von Viv bekommen habe.
Wie auch immer, ich dachte mir, ich würde die Lösung teilen, die ich mir hier ausgedacht habe, vielleicht hilft sie jemandem auf dem Weg.
void Switch::on_sldSwitch_actionTriggered(int action) {
if(action != 7) ui->sldSwitch->setValue((action%2) ? 100 : 0);
}
void Switch::on_sldSwitch_sliderReleased() {
ui->sldSwitch->setValue((ui->sldSwitch->sliderPosition() >= 50) ? 100 : 0);
}
eine kleine Erklärung: actionTriggered
wird jedes Mal aufgerufen werden, der Schieber geklickt wird oder mit der Tastatur bewegt. Wenn es gezogen wird, wird es das Signal "7" ausgeben. Um ein sofortiges Fangen zu vermeiden, wird Aktion 7 blockiert.
Wenn Sie nach rechts bewegen, wird beim Klicken 3 und beim Klicken 1 "rechts" (oder "unten") auf der Tastatur angezeigt, weshalb wir nach rechts springen, wenn es sich nicht um eine gerade Zahl handelt.
Wenn links bewegt, emittiert er 2 oder 4
sliderReleased()
wird aufgerufen, wenn Sie in diesem Augenblick Sie die Maustaste loslassen, aber nach dem Ziehen weist der Schieber noch seinen alten Wert (die mich gestolpert ziemlich viel). Also, um die richtige Position zum Einrasten zu bekommen, habe ich sliderPosition
statt value
abgefragt und das ist das.
Ich hoffe, das hilft jemandem. Hier
ein Beispiel:
switch.h
:
#pragma once
#include <QtWidgets>
class Switch : public QAbstractButton {
Q_OBJECT
Q_PROPERTY(int offset READ offset WRITE setOffset)
Q_PROPERTY(QBrush brush READ brush WRITE setBrush)
public:
Switch(QWidget* parent = nullptr);
Switch(const QBrush& brush, QWidget* parent = nullptr);
QSize sizeHint() const override;
QBrush brush() const {
return _brush;
}
void setBrush(const QBrush &brsh) {
_brush = brsh;
}
int offset() const {
return _x;
}
void setOffset(int o) {
_x = o;
update();
}
protected:
void paintEvent(QPaintEvent*) override;
void mouseReleaseEvent(QMouseEvent*) override;
void enterEvent(QEvent*) override;
private:
bool _switch;
qreal _opacity;
int _x, _y, _height, _margin;
QBrush _thumb, _track, _brush;
QPropertyAnimation *_anim = nullptr;
};
switch.cpp
:
Switch::Switch(QWidget *parent) : QAbstractButton(parent),
_height(16),
_opacity(0.000),
_switch(false),
_margin(3),
_thumb("#d5d5d5"),
_anim(new QPropertyAnimation(this, "offset", this))
{
setOffset(_height/2);
_y = _height/2;
setBrush(QColor("#009688"));
}
Switch::Switch(const QBrush &brush, QWidget *parent) : QAbstractButton(parent),
_height(16),
_switch(false),
_opacity(0.000),
_margin(3),
_thumb("#d5d5d5"),
_anim(new QPropertyAnimation(this, "offset", this))
{
setOffset(_height/2);
_y = _height/2;
setBrush(brush);
}
void Switch::paintEvent(QPaintEvent *e) {
QPainter p(this);
p.setPen(Qt::NoPen);
if (isEnabled()) {
p.setBrush(_switch ? brush() : Qt::black);
p.setOpacity(_switch ? 0.5 : 0.38);
p.setRenderHint(QPainter::Antialiasing, true);
p.drawRoundedRect(QRect(_margin, _margin, width() - 2 * _margin, height() - 2 * _margin), 8.0, 8.0);
p.setBrush(_thumb);
p.setOpacity(1.0);
p.drawEllipse(QRectF(offset() - (_height/2), _y - (_height/2), height(), height()));
} else {
p.setBrush(Qt::black);
p.setOpacity(0.12);
p.drawRoundedRect(QRect(_margin, _margin, width() - 2 * _margin, height() - 2 * _margin), 8.0, 8.0);
p.setOpacity(1.0);
p.setBrush(QColor("#BDBDBD"));
p.drawEllipse(QRectF(offset() - (_height/2), _y - (_height/2), height(), height()));
}
}
void Switch::mouseReleaseEvent(QMouseEvent *e) {
if (e->button() & Qt::LeftButton) {
_switch = _switch ? false : true;
_thumb = _switch ? _brush : QBrush("#d5d5d5");
if (_switch) {
_anim->setStartValue(_height/2);
_anim->setEndValue(width() - _height);
_anim->setDuration(120);
_anim->start();
} else {
_anim->setStartValue(offset());
_anim->setEndValue(_height/2);
_anim->setDuration(120);
_anim->start();
}
}
QAbstractButton::mouseReleaseEvent(e);
}
void Switch::enterEvent(QEvent *e) {
setCursor(Qt::PointingHandCursor);
QAbstractButton::enterEvent(e);
}
QSize Switch::sizeHint() const {
return QSize(2 * (_height + _margin), _height + 2 * _margin);
}
main.cpp
:
#include "switch.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QWidget *widget = new QWidget;
widget->setWindowFlags(Qt::FramelessWindowHint);
QHBoxLayout layout;
widget->setLayout(&layout);
Switch *_switch = new Switch;
Switch *_switch2 = new Switch;
_switch2->setDisabled(true);
layout.addWidget(_switch);
layout.addWidget(_switch2);
widget->show();
return a.exec();
}
Diese Klasse ist großartig, aber sie benötigt einen Aufruf an 'QAbstractButton :: mouseReleaseEvent (e);' am Ende von void 'Switch :: mouseReleaseEvent (QMouseEvent * e)'. Dies wird dazu beitragen, dass der Knopf alle richtigen Signale aussendet, wenn er angeklickt wird. – Brandon
Ja, es ist gute Praxis, Basisklasse implementation.thanks zu nennen – IMAN4K
- 1. UIBarButtonItem als Kippschalter für Boolesche
- 2. Mehrere Kippschalter auf Seite CSS
- 3. Qt: Unbekannte Module in QT: webview
- 4. Libvirt in Fehler Qt während in Qt Creator kompilieren
- 5. Persistenz-Klassen in Qt
- 6. Eingebettete Datenbank in Qt
- 7. Wie Einstellungen in Qt
- 8. glTexImage3D stürzt in QT
- 9. Bild drehen in Qt
- 10. Zeileninterpolation in Qt?
- 11. Bildschirmtastatur in Qt 5
- 12. Unload Plugin in Qt
- 13. GIF-Animation in Qt
- 14. Ausnahmesicherheit in Qt
- 15. Debuggen in Qt Creator
- 16. unique_ptr in Qt-Projekt
- 17. Druckbogen in Qt
- 18. Regulärer Ausdruck in Qt
- 19. undefined reference in qt
- 20. Eröffnungsdatei in Qt
- 21. //! [0] in Qt-Quelltext
- 22. glMultiDrawArrays in QT?
- 23. Hierarchie in Qt [C++]
- 24. Unterbrechbarer Schlaf in Qt?
- 25. Making Grundstück in Qt
- 26. wie Kontaktliste in qt
- 27. Downcasting in Qt
- 28. Qt + OpenCV in Debian
- 29. Einzelinstanz-Anwendung in Qt
- 30. Smart Pointer in Qt
Ehrfürchtiger Mann! Schöne "Snap-To-End" -Effekte werden durch den Trick erzielt, den Sie hier geteilt haben! Ich habe den Code für das gleiche hinzugefügt, damit die Leute es besser und besser verstehen können. – zeFree