DEV Community

Mate Technologies
Mate Technologies

Posted on

🧱 Building QRForge PRO with PySide6 (Beginner-Friendly Guide)

This tutorial is a Dev.to–style, step-by-step walkthrough of the QRForge PRO v2.0.0 desktop application.

We’ll progressively build a professional QR code design studio using:

🐍 Python

🖼 PySide6 (Qt for Python)

🔳 qrcode

🧠 GraphicsScene / GraphicsView

📤 PNG, SVG, and PDF exports

👉 Full source code: https://github.com/rogers-cyber/QRForgePRO

0️⃣ What You’ll Build

By the end, you’ll have an app that can:

Generate QR codes from Text, URLs, and Wi‑Fi credentials

Customize colors, backgrounds, transparency

Move, rotate, and scale QRs visually

Export print‑ready PNG, SVG, and PDF files

1️⃣ Project Setup
Install dependencies
pip install PySide6 qrcode pillow requests
File structure
qrforge/
├─ main.py
├─ logo.ico
2️⃣ Importing What We Need

We start by importing system utilities, Qt widgets, and QR helpers.

import sys, os, math, requests
import qrcode
from PIL import Image
Qt imports
from PySide6.QtWidgets import *
from PySide6.QtGui import *
from PySide6.QtCore import *
from PySide6.QtSvg import QSvgGenerator
from PySide6.QtGui import QPdfWriter, QPageSize
Enter fullscreen mode Exit fullscreen mode

👉 These give us:

Windows & dialogs

Vector drawing

Scene-based rendering

SVG/PDF export

3️⃣ App Metadata

Centralized metadata keeps things clean and reusable.

APP_NAME = "QRForge PRO"
APP_VERSION = "2.0.0"
APP_AUTHOR = "Mate Technologies"
APP_URL = "https://matetools.gumroad.com"
Enter fullscreen mode Exit fullscreen mode

4️⃣ Utility Functions
Resource loader (for PyInstaller compatibility)

def resource_path(name):
    base = getattr(sys, "_MEIPASS", os.path.dirname(__file__))
    return os.path.join(base, name)
URL shortener (TinyURL API)
def shorten_url(url):
    try:
        r = requests.get(f"https://tinyurl.com/api-create.php?url={url}", timeout=5)
        return r.text if r.status_code == 200 else url
    except:
        return url
Wi‑Fi QR payload format
def wifi_payload(ssid, pwd, enc):
    return f"WIFI:S:{ssid};T:{enc if enc!='NONE' else ''};P:{pwd};;"
Enter fullscreen mode Exit fullscreen mode

5️⃣ Creating a QR Code Graphics Item

Instead of rendering images directly, we create a custom QGraphicsItem. This allows:

Dragging

Rotation

Selection outlines

QRItem class

class QRItem(QGraphicsItem):
    def __init__(self, data):
        super().__init__()
        self.data = data
        self.size = 300
        self.rotation_angle = 0
        self.fill = QColor("black")
        self.bg = QColor("white")
        self.transparent = False
        self.generate()
Enter fullscreen mode Exit fullscreen mode

Generating the QR image

    def generate(self):
        qr = qrcode.QRCode(border=1)
        qr.add_data(self.data)
        qr.make(fit=True)


        back = None if self.transparent else self.bg.name()
        img = qr.make_image(
            fill_color=self.fill.name(),
            back_color=back
        ).convert("RGBA")
Converting PIL → QImage
        self.qimage = QImage(
            img.tobytes("raw", "RGBA"),
            img.width,
            img.height,
            QImage.Format_RGBA8888
        )
Enter fullscreen mode Exit fullscreen mode

Painting & selection outline

    def paint(self, p, *_):
        p.save()
        p.rotate(self.rotation_angle)
        p.drawImage(self.boundingRect(), self.qimage)
        p.restore()


        if self.isSelected():
            p.setPen(QPen(QColor("#00E676"), 2, Qt.DashLine))
            p.drawRect(self.boundingRect())
Enter fullscreen mode Exit fullscreen mode

6️⃣ Canvas: Zoom, Drag, Rotate

We extend QGraphicsView for interaction.

class Canvas(QGraphicsView):
def wheelEvent(self, e):
self.scale(1.15 if e.angleDelta().y() > 0 else 0.85,
1.15 if e.angleDelta().y() > 0 else 0.85)
ALT + mouse rotation
def mouseMoveEvent(self, e):
if self.rotating:
item = self.itemAt(e.position().toPoint())
if isinstance(item, QRItem):
dx = e.scenePosition().x() - item.scenePos().x()
dy = e.scenePosition().y() - item.scenePos().y()
item.rotation_angle = math.degrees(math.atan2(dy, dx))
item.update()
7️⃣ Main Window (QMainWindow)

This is where everything comes together.

class QRForgeStudio(QMainWindow):

    def __init__(self):
        super().__init__()
        self.scene = QGraphicsScene(-5000, -5000, 10000, 10000)
        self.canvas = Canvas(self.scene)
        self.setCentralWidget(self.canvas)
Enter fullscreen mode Exit fullscreen mode

8️⃣ Left Control Panel (DockWidget)
Mode selector

self.mode = QComboBox()
self.mode.addItems(["Text", "URL", "Wi‑Fi"])
Enter fullscreen mode Exit fullscreen mode

Content input

self.text = QTextEdit()
self.text.setPlaceholderText("Enter content…")
Color & background controls
self.fill_btn = QPushButton("🎨 Fill Color")
self.bg_btn = QPushButton("🖌 Background")
self.trans = QCheckBox("Transparent Background")
Enter fullscreen mode Exit fullscreen mode

9️⃣ Adding a QR to the Canvas

def add_qr(self):
    mode = self.mode.currentText()
    if mode == "Text":
        data = self.text.toPlainText()
    elif mode == "URL":
        data = shorten_url(self.text.toPlainText())
    else:
        data = wifi_payload(self.ssid.text(), self.pwd.text(), self.enc.currentText())


    item = QRItem(data)
    self.scene.addItem(item)
    item.setPos(0, 0)
Enter fullscreen mode Exit fullscreen mode

🔟 Exporting (PNG, SVG, PDF)
PNG export (raster)

img = QImage(width, height, QImage.Format_ARGB32)
self.scene.render(painter)
img.save(path)
SVG export (vector)
svg = QSvgGenerator()
svg.setViewBox(rect)
self.scene.render(painter)
PDF export (print-ready)
pdf = QPdfWriter(path)
pdf.setPageSize(QPageSize.A4)
pdf.setResolution(300)
Enter fullscreen mode Exit fullscreen mode

Each QR gets its own page.

1️⃣1️⃣ Entry Point

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = QRForgeStudio()
    win.show()
    sys.exit(app.exec())
Enter fullscreen mode Exit fullscreen mode

🎉 Final Result

You now have:

A designer-friendly QR studio

Vector & print exports

Interactive canvas controls

Clean PySide6 architecture

👉 Full repository: https://github.com/rogers-cyber/QRForgePRO

🚀 What to Build Next

Preset templates

Logo embedding

Batch QR generation

PyInstaller packaging

Happy building! 🧡

I’ve created a Dev.to–style, beginner-friendly, step-by-step tutorial in the canvas that walks through QRForge PRO from zero to a complete app.

What this version does differently (on purpose)

✅ Breaks the project into small, digestible sections

✅ Uses short code blocks with explanations right after

✅ Explains why each Qt / QR concept exists, not just what

✅ Keeps it friendly for developers new to PySide6 + GraphicsView

✅ Links to the full source code clone without dumping unreadable walls of code

Perfect for:

Dev.to publishing

Medium / Hashnode cross-posts

Open-source project documentation

Teaching PySide6 visually

QR code design

Top comments (0)