Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Drawing WiFi Signal Strength Icons with QPainter in Qt

Tech 2

This article demonstratse how to create WiFi signal strength icons in Qt applications, similar to those found on mobile devices. These icons visually represent the connection quality between a device and a wireless network, helping users understand their network connectivity and take appropriate actions like repositioning devices or extending router coverage.

Overview

The implementation uses a custom QWidget called WifiIcon to render signal strength indicators. The paintEvent method handles the drawing operations using QPainter, while setStrength allows dynamic updates to the signal display.

Implementation

Header File

#ifndef WIFICONNECTIVITYICON_H
#define WIFICONNECTIVITYICON_H

#include <QWidget>

class WifiConnectivityIcon : public QWidget
{
    Q_OBJECT

public:
    explicit WifiConnectivityIcon(QWidget *parent = nullptr);

    enum SignalLevel {
        None = 0,
        Weak,
        Fair,
        Good,
        Excellent
    };

    void updateSignalLevel(SignalLevel level);

protected:
    void paintEvent(QPaintEvent *) override;
    void renderArcSegment(QPainter *painter, int radius, int startAngle, int spanAngle, int thickness);

private:
    SignalLevel currentSignalLevel;
};

#endif // WIFICONNECTIVITYICON_H

Implementation File

#include "wificonnectivityicon.h"
#include <QPainter>
#include <QPainterPath>

WifiConnectivityIcon::WifiConnectivityIcon(QWidget *parent) : QWidget(parent)
{
    currentSignalLevel = SignalLevel::None;
}

void WifiConnectivityIcon::paintEvent(QPaintEvent *)
{
    QPainter canvas(this);
    canvas.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    const qreal widgetWidth = width();
    const qreal widgetHeight = height();
    
    const int minDimension = qMin(widgetWidth, widgetHeight);
    
    const qreal baseRadius = minDimension / 9.5;
    const qreal maxArcRadius = widgetHeight * 0.85;
    const int arcThickness = widgetHeight / 10.5;

    const QColor activeColor = Qt::white;
    const QColor inactiveColor = QColor(100, 100, 100);
    
    int activeSegments = 0;
    switch(currentSignalLevel) {
    case Excellent: activeSegments = 4; break;
    case Good:      activeSegments = 3; break;
    case Fair:      activeSegments = 2; break;
    case Weak:      activeSegments = 1; break;
    default:        activeSegments = 0; break;
    }

    for (int segment = 1; segment <= 4; ++segment) {
        if (segment <= activeSegments && activeSegments > 0) {
            canvas.setBrush(activeColor);
            canvas.setPen(activeColor);
        } else {
            canvas.setBrush(inactiveColor);
            canvas.setPen(inactiveColor);
        }

        switch (segment) {
        case 1: // Center dot
            canvas.drawEllipse(QPointF(widgetWidth * 0.5, widgetHeight * 0.88), baseRadius, baseRadius);
            canvas.translate(QPointF(widgetWidth * 0.5, widgetHeight * 0.9));
            break;
        case 2: // Inner arc
            renderArcSegment(&canvas, maxArcRadius * 0.40, 45, 90, arcThickness);
            break;
        case 3: // Middle arc
            renderArcSegment(&canvas, maxArcRadius * 0.70, 45, 90, arcThickness);
            break;
        case 4: // Outer arc
            renderArcSegment(&canvas, maxArcRadius, 45, 90, arcThickness);
            break;
        }
    }
}

void WifiConnectivityIcon::renderArcSegment(QPainter *painter, int radius, int startAngle, int spanAngle, int thickness)
{
    QRectF outerBounds(-radius, -radius, radius * 2, radius * 2);
    QPainterPath arcPath;
    arcPath.arcTo(outerBounds, startAngle, spanAngle);

    QPainterPath innerCutout;
    innerCutout.addEllipse(outerBounds.adjusted(thickness, thickness, -thickness, -thickness));

    arcPath -= innerCutout;
    painter->drawPath(arcPath);
}

void WifiConnectivityIcon::updateSignalLevel(SignalLevel level)
{
    currentSignalLevel = level;
    update();
}

Usage

To use this component, simply instantiate WifiConnectivityIcon in your main window and call updateSignalLevel() whenever the WiFi signal changes. The widget will automatically redraw to reflect the new signal strength.

This basic implementation can be extended with features like real-time updates, animations, or customizable styling based on application requirements.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.