Qt custom control (switch button)
-
- principle
- Source code
- operation result
Children who have been exposed to the IOS system should be familiar with the switch button. They often encounter it in the settings. The sliding effect when switching is quite cool.
Generally speaking, the switch button has two states: on and off.
Next, we use custom controls to implement a switch button.
Principle
Override the mouse press event (mousePressEvent) and release event (mouseReleaseEvent) to switch the switch state.
Override the painting event (paintEvent), used to draw the switch effect.
Use QTimer to refresh regularly to produce animation effects when the switch is switched.
The remaining interfaces are used for expansion and can also be expanded by yourself.
Source code
SwitchControl.h
#ifndef SWITCHCONTROL_H #define SWITCHCONTROL_H #include <QObject> #include <QWidget> #include <QTimer> class SwitchControl : public QWidget {<!-- --> Q_OBJECT public: explicit SwitchControl(QWidget *parent = nullptr); // Return switch status - open: true, closed: false bool isToggled() const; //Set switch status void setToggle(bool checked); //Set background color void setBackgroundColor(QColor color); //Set selected color void setCheckedColor(QColor color); //Set unavailable colors void setDisbaledColor(QColor color); protected: // draw switch void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; //Mouse press event void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; // Mouse release event - toggle switch status and emit toggled() signal void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; // size change event void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; signals: //When the state changes, emit a signal void toggled(bool checked); private slots: // Used to produce a sliding effect when switching states void onTimeout(); private: bool m_bChecked; // Is it selected? QColor m_background; // Background color QColor m_checkedColor; // selected color QColor m_disabledColor; // Disabled color QColor m_thumbColor; // Thumb color qreal m_radius; // rounded corners qreal m_nX; // x point coordinates qreal m_nY; // y point coordinates qint16 m_nHeight; // height qint16 m_nMargin; // Margin QTimer m_timer; // timer }; #endif // SWITCHCONTROL_H
SwitchControl.cpp
#include <QPainter> #include <QMouseEvent> #include "switchcontrol.h" SwitchControl::SwitchControl(QWidget *parent) : QWidget(parent), m_bChecked(false), m_background(Qt::black), m_checkedColor(QColor(0, 150, 136)), m_disabledColor(QColor(190, 190, 190)), m_thumbColor(Qt::white), m_radius(32.0), m_nHeight(64), m_nMargin(0) {<!-- --> // Mouse slides over the cursor shape - hand shape setCursor(Qt::PointingHandCursor); setFixedSize(m_nHeight*3, m_nHeight); // Connect signal slot connect( & amp;m_timer, SIGNAL(timeout()), this, SLOT(onTimeout())); } // draw switch void SwitchControl::paintEvent(QPaintEvent *event) {<!-- --> Q_UNUSED(event); QPainter painter(this); painter.setPen(Qt::NoPen); painter.setRenderHint(QPainter::Antialiasing); QPainterPath path; QColor background; QColor thumbColor; qreal dOpacity; QString stateStr; QRectFrect; QPen pen(QBrush(QColor(255, 255, 255)), 1); QFont font("黑体", 28, QFont::Normal); if (isEnabled()) {<!-- --> // Available status if (m_bChecked) {<!-- --> // open state background = m_checkedColor; thumbColor = m_checkedColor; dOpacity = 0.600; stateStr = QString("On"); QFontMetrics fmt(font); int textWidth = fmt.horizontalAdvance(stateStr); int textHeight = fmt.height(); rect = QRectF(height()*0.3, height()*0.1, textWidth, textHeight); } else {<!-- --> //Close state background = m_background; thumbColor = m_thumbColor; dOpacity = 0.800; stateStr = QString("Off"); QFontMetrics fmt(font); int textWidth = fmt.horizontalAdvance(stateStr); int textHeight = fmt.height(); rect = QRectF(height()*1.3, height()*0.1, textWidth, textHeight); } } else {<!-- --> // Unavailable state background = m_background; dOpacity = 0.260; thumbColor = m_disabledColor; } //Draw a large ellipse painter.setBrush(background); painter.setOpacity(dOpacity); path.addRoundedRect(QRectF(m_nMargin, m_nMargin, width() - 2 * m_nMargin, height() - 2 * m_nMargin), m_radius, m_radius); painter.drawPath(path.simplified()); qDebug("x:%d, y:%d, w:%d, h:%d\\ ", m_nMargin, m_nMargin, width() - 2 * m_nMargin, height() - 2 * m_nMargin); //Draw a small ellipse painter.setBrush(thumbColor); painter.setOpacity(1.0); painter.drawEllipse(QRectF(m_nX - (m_nHeight / 2), m_nY - (m_nHeight / 2), height(), height())); painter.setPen(pen); painter.setFont(font); painter.drawText(rect, Qt::AlignCenter, stateStr); } //Mouse press event void SwitchControl::mousePressEvent(QMouseEvent *event) {<!-- --> if (isEnabled()) {<!-- --> if (event->buttons() & amp; Qt::LeftButton) {<!-- --> event->accept(); } else {<!-- --> event->ignore(); } } } // Mouse release event - toggle switch status and emit toggled() signal void SwitchControl::mouseReleaseEvent(QMouseEvent *event) {<!-- --> if (isEnabled()) {<!-- --> if ((event->type() == QMouseEvent::MouseButtonRelease) & amp; & amp; (event->button() == Qt::LeftButton)) {<!-- --> event->accept(); m_bChecked = !m_bChecked; emit toggled(m_bChecked); m_timer.start(3); } else {<!-- --> event->ignore(); } } } // size change event void SwitchControl::resizeEvent(QResizeEvent *event) {<!-- --> m_nX = m_nHeight / 2; m_nY = m_nHeight / 2; QWidget::resizeEvent(event); } // Switch state - sliding void SwitchControl::onTimeout() {<!-- --> if (m_bChecked) {<!-- --> m_nX + = 1; if (m_nX >= width() - m_nHeight/2) m_timer.stop(); } else {<!-- --> m_nX -= 1; if (m_nX <= m_nHeight / 2) m_timer.stop(); } update(); } // Return switch status - open: true, closed: false bool SwitchControl::isToggled() const {<!-- --> return m_bChecked; } //Set switch status void SwitchControl::setToggle(bool checked) {<!-- --> m_bChecked = checked; m_timer.start(10); } //Set background color void SwitchControl::setBackgroundColor(QColor color) {<!-- --> m_background = color; } //Set selected color void SwitchControl::setCheckedColor(QColor color) {<!-- --> m_checkedColor = color; } //Set unavailable colors void SwitchControl::setDisbaledColor(QColor color) {<!-- --> m_disabledColor = color; }
For demonstration, you can set the switch style, status and other effects. Calling code:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) {<!-- --> ui->setupUi(this); SwitchControl *pSwitchControl = new SwitchControl(this); SwitchControl *pGreenSwitchControl = new SwitchControl(this); SwitchControl *pDisabledSwitchControl = new SwitchControl(this); QVBoxLayout* vbox = new QVBoxLayout; ui->centralwidget->setLayout(vbox); vbox->addWidget(pSwitchControl, 1); vbox->addWidget(pGreenSwitchControl); vbox->addWidget(pDisabledSwitchControl); //Set status and style pGreenSwitchControl->setToggle(true); pGreenSwitchControl->setCheckedColor(QColor(0, 160, 230)); pGreenSwitchControl->setBackgroundColor(QColor(255, 99, 71)); pDisabledSwitchControl->setEnabled(true); pDisabledSwitchControl->setToggle(true); // Connect signal slot connect(pSwitchControl, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool))); } void MainWindow::onToggled(bool bChecked) {<!-- --> qDebug() << "State : " << bChecked; }