Qt Custom Image - Based Toggle Switch Widget

Overview

This guide introduces the creation of a Qt custom widget for an image - based toggle switch. The widget utilizes different images for the 'on' and 'off' states, supports mouse interaction, and offers multiple visual styles.

Design Approcah

Inherit from QWidget to develop a reusable component. It manages the toggle state and image resources, handles mouse events (for toggling) and paint events (for rendering the current image), and exposes properties and signals for integration.

Core Code

Header File (picToggle.h)

#ifndef PICTOGGLE_H
#define PICTOGGLE_H

#include <QWidget>
class PicToggle : public QWidget
{
    Q_OBJECT
    Q_ENUMS(StyleType)

    Q_PROPERTY(bool toggled READ isToggled WRITE setToggled)
    Q_PROPERTY(StyleType style READ getStyle WRITE setStyle)

public:
    enum StyleType {
        Style_1 = 0,  // Style variant 1
        Style_2 = 1,  // Style variant 2
        Style_3 = 2   // Style variant 3
    };

    explicit PicToggle(QWidget *parent = nullptr);

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void paintEvent(QPaintEvent *event) override;

private:
    bool toggled;             // Toggle state
    StyleType style;          // Visual style
    QString imgOff;           // Off - state image path
    QString imgOn;            // On - state image path
    QString currentImg;       // Currently displayed image

public:
    QSize sizeHint() const override;
    QSize minimumSizeHint() const override;

    bool isToggled() const;
    void setToggled(bool state);

    StyleType getStyle() const;
    void setStyle(const PicToggle::StyleType &newStyle);

Q_SIGNALS:
    void toggledChanged(bool toggled);
};

#endif // PICTOGGLE_H

Implementation File (picToggle.cpp)

#include "picToggle.h"
#include <QPainter>

PicToggle::PicToggle(QWidget *parent) : QWidget(parent)
{
    toggled = false;
    style = Style_2;

    imgOff = ":/res/toggle/off2.png";
    imgOn = ":/res/toggle/on2.png";
    currentImg = imgOff;
}

void PicToggle::mousePressEvent(QMouseEvent *)
{
    toggled = !toggled;
    currentImg = toggled ? imgOn : imgOff;
    emit toggledChanged(toggled);
    update();
}

void PicToggle::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.setRenderHint(QPainter::SmoothPixmapTransform);
    QImage img(currentImg);
    img = img.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);

    QPoint center(rect().center().x() - img.width() / 2, rect().center().y() - img.height() / 2);
    p.drawImage(center, img);
}

QSize PicToggle::sizeHint() const
{
    return QSize(87, 28);
}

QSize PicToggle::minimumSizeHint() const
{
    return QSize(87, 28);
}

bool PicToggle::isToggled() const
{
    return toggled;
}

void PicToggle::setToggled(bool state)
{
    if (toggled != state) {
        toggled = state;
        currentImg = state ? imgOn : imgOff;
        update();
    }
}

PicToggle::StyleType PicToggle::getStyle() const
{
    return style;
}

void PicToggle::setStyle(const PicToggle::StyleType &newStyle)
{
    if (style != newStyle) {
        style = newStyle;

        if (newStyle == Style_1) {
            imgOff = ":/res/toggle/off1.png";
            imgOn = ":/res/toggle/on1.png";
            resize(87, 28);
        } else if (newStyle == Style_2) {
            imgOff = ":/res/toggle/off2.png";
            imgOn = ":/res/toggle/on2.png";
            resize(87, 28);
        } else if (newStyle == Style_3) {
            imgOff = ":/res/toggle/off3.png";
            imgOn = ":/res/toggle/on3.png";
            resize(96, 38);
        }

        currentImg = toggled ? imgOn : imgOff;
        setToggled(toggled);
        update();
        updateGeometry();
    }
}

Usage Example

Integrate PicToggle in a Qt form (e.g., frmPicToggle.cpp):

#include "frmPicToggle.h"
#include "ui_frmPicToggle.h"
#include "qdebug.h"

frmPicToggle::frmPicToggle(QWidget *parent) : QWidget(parent), ui(new Ui::frmPicToggle)
{
    ui->setupUi(this);
    initUI();
}

frmPicToggle::~frmPicToggle()
{
    delete ui;
}

void frmPicToggle::initUI()
{
    ui->toggle1->setToggled(true);
    ui->toggle2->setToggled(true);
    ui->toggle3->setToggled(true);

    ui->toggle1->setFixedSize(160, 60);
    ui->toggle2->setFixedSize(160, 60);
    ui->toggle3->setFixedSize(160, 60);

    ui->toggle1->setStyle(PicToggle::Style_1);
    ui->toggle2->setStyle(PicToggle::Style_2);
    ui->toggle3->setStyle(PicToggle::Style_3);

    connect(ui->toggle1, SIGNAL(toggledChanged(bool)), this, SLOT(onToggleChanged(bool)));
    connect(ui->toggle2, SIGNAL(toggledChanged(bool)), this, SLOT(onToggleChanged(bool)));
    connect(ui->toggle3, SIGNAL(toggledChanged(bool)), this, SLOT(onToggleChanged(bool)));
}

void frmPicToggle::onToggleChanged(bool state)
{
    qDebug() << sender() << state;
}

The widget toggles between states on mouse click, updates the displayed image, and emits a signal. Use setToggled() to control the state programmatically, and setStyle() to switch visual variants. Ensure that image resources (e.g., off1.png, on2.png) are added to the project's resource file.

Tags: Qt Custom Widget Toggle Switch Image Switch C++

Posted on Mon, 27 Jul 2026 17:07:15 +0000 by enormousrodent