/* --- Conteneur du formulaire --- */
QWidget#FormContainer {
background-color: #111;
border-radius: 20px;
padding: 40px;
margin-right: 60px;
border: 2px solid #e63946; /* bordure rouge plus visible */
box-shadow: 0px 10px 30px rgba(0,0,0,0.6);
}
/* --- Titres --- */
QLabel#Title {
font-size: 38px;
color: #e63946;
margin-bottom: 5px;
font-weight: bold;
letter-spacing: 1px;
}
QLabel#Subtitle {
font-size: 18px;
color: #ccc;
margin-bottom: 30px;
font-weight: 400;
}
/* --- Labels --- */
QLabel {
font-size: 14px;
color: #ddd;
}
/* --- Champs de saisie --- */
QLineEdit {
width: 100%;
padding: 12px;
border-radius: 12px;
border: 1px solid #444;
background-color: #1b1b1b;
color: #fff;
font-size: 14px;
transition: all 0.3s;
}
QLineEdit:focus {
border: 2px solid #e63946;
background-color: #222;
}
/* --- Bouton Se connecter --- */
QPushButton {
width: 100%;
padding: 14px;
background-color: #e63946;
border: none;
border-radius: 12px;
font-size: 16px;
color: #fff;
font-weight: bold;
cursor: pointer;
transition: all 0.3s;
}
QPushButton:hover {
background-color: #d62828;
transform: scale(1.03);
}
/* --- Message d'erreur --- */
QLabel#MessageLabel {
background-color: #330000;
border-left: 4px solid #e63946;
padding: 12px;
border-radius: 8px;
margin-top: 15px;
color: #fff;
}
/* --- Lien inscription --- */
QLabel#RegisterLink {
color: #e63946;
font-weight: bold;
margin-top: 10px;
}
QLabel#RegisterLink:hover {
color: #ff4d4d;
text-decoration: underline;
}
/* --- Fond gauche (optionnel pour décor) --- */
QWidget#LeftContainer {
background: qlineargradient(
x1:0, y1:0, x2:1, y2:1,
stop:0 #0f0f0f,
stop:1 #1a1a1a
);
border-top-left-radius: 20px;
border-bottom-left-radius: 20px;
}
Comment corriger
Assurer que les objectName correspondent
Exemple : dans le QSS tu as QLabel#Title, donc dans Python :
Python
Copier le code
title = QLabel("Bienvenue")
[Link]("Title")
✅ C’est correct.
Charger le QSS correctement
Remplace :
Python
Copier le code
[Link]([Link]() + [Link]())
Par :
Python
Copier le code
with open(qss_path, "r", encoding="utf-8") as f:
[Link]([Link]())
Ou mieux : combine tout en une seule chaîne pour éviter les conflits.
Ne pas mettre un style global trop général
Ton style actuel :
CSS
Copier le code
QWidget { color: #fff; }
affecte tous les labels. Il vaut mieux limiter le style global au fond et polices, et laisser les couleurs de texte spécifiques
dans le QSS. Par exemple :
CSS
Copier le code
QWidget {
background: qlineargradient(...);
font-family: 'Segoe UI', sans-serif;
}
Vérifier le chemin du QSS
Si qss_path est incorrect, Qt ne trouve pas le fichier et reste avec le style par défaut.
Similitudes avec CSS
La syntaxe de base est la même :
CSS
Copier le code
QPushButton {
background-color: #e63946;
border-radius: 8px;
}
QPushButton:hover {
background-color: #d62828;
}
Tu peux utiliser #id (objectName), .class (QWidget avec setProperty("class","...")), et pseudo-états comme :hover, :pressed,
:focus.
2. Limitations par rapport au CSS
Fonction CSS
Support dans QSS
flex, grid
❌ non supporté (Qt utilise ses propres Layouts)
@media
❌ non supporté
animation / transition
❌ très limité (Qt a QPropertyAnimation mais pas via QSS)
box-shadow
✅ limité à shadow: ... sur certains widgets
background-image, border-radius
✅ supportés, mais parfois pas sur tous les widgets
Donc tu ne peux pas copier/coller directement ton CSS web dans un .qss sans ajustements.
3. Bonnes pratiques
Utiliser QSS pour la couleur, bordures, coins arrondis, hover, focus.
Utiliser layouts Qt pour organiser les widgets (pas flex ou grid).
Pour les animations et effets avancés : utiliser QPropertyAnimation ou QGraphicsEffect.
✅ Conclusion
CSS pur → non, ça ne fonctionne pas directement.
QSS → oui, très proche du CSS et suffisant pour styliser ton application.
Tu peux utiliser qdarkstyle ou pyqt-material si tu veux un style moderne prêt à l’emploi et ajouter ton QSS par-dessus.
Résumé rapide
Eel → facile à développer, front web + Python. On emballe Python avec PyInstaller (ou cx_Freeze) et on inclut le dossier
web. Résultat : .exe.
PyWebview → léger, fenêtre native affichant ton HTML. Procédé d’emballage similaire à Eel (PyInstaller).
Electron + Python → rendu web natif (Chromium), look 100% identique au site. Emballage plus lourd : on package l’app
Electron (avec electron-builder) et on bundle le backend Python (PyInstaller) ou on communique avec un service Python
local. Plus professionnel mais plus de travail.
Détails pratiques et étapes pour Windows
Option A — Eel / PyWebview (recommandé si tu veux réutiliser ton site rapidement)
Structure :
Copier le code
projet/
[Link]
web/ # ton HTML/CSS/JS du site
[Link]
Développer : expose des fonctions Python (API internes) que ton JS appelle.
Tester localement.
Packager avec PyInstaller (exemple pour PyWebview/Eel) :
Exemple de commande (depuis la racine du projet) :
Bash
Copier le code
pip install pyinstaller
pyinstaller --noconsole --onefile --add-data "web;web" [Link]
--onefile : produit un seul .exe (plus lent au démarrage).
--add-data "web;web" : inclut ton dossier web (sous Windows sépare par ;).
Si tu utilises des modules cachés, ajoute --hidden-import=module_name.
Résultat : dist/[Link] → renommer en [Link]. Tu peux ensuite créer un installateur (Inno Setup, NSIS, ou même zip
simple).
Points à vérifier
Inclure les fichiers statiques (images, fonts).
Certaines dépendances (requests, cryptography...) peuvent demander des options supplémentaires.
Tester sur une VM Windows propre (sans Python installé) pour valider l’exécutable.
Option B — Electron (le plus lourd mais rendu identique au navigateur)
Frontend : ton HTML/CSS/JS (ou une app React/Vue).
Backend Python :
Soit python embeddé et lancé par Electron (processus enfant) ;
soit empaqueter le backend avec PyInstaller en un exe et l’appeler depuis Electron.
Packager :
Utiliser electron-builder pour créer l’installateur .exe (ou .msi).
Inclure le backend Python packagé en exe dans le binaire Electron ou l’installeur.
Flux résumé :
pyinstaller [Link] → [Link]
electron-builder package l’UI + intègre [Link] dans resources et crée l’installateur final.
Avantages
Interface identique au site (Chromium).
Très pro, facile d’obtenir un exécutable multi-plateformes.
Inconvénients
Très lourd (taille finale souvent > 50–100 MB).
Build plus complexe (deux toolchains à gérer : Node/Electron + Python).
Outils d’emballage & installateurs recommandés
PyInstaller — créer .exe depuis Python (très utilisé).
Commande de base : pyinstaller --onefile --add-data "web;web" [Link]
cx_Freeze — alternative à PyInstaller.
Inno Setup / NSIS — créer un installateur Windows ([Link]).
electron-builder — pour Electron, crée .exe/installers multiplateformes.
signtool (optionnel) — signer l’exe pour éviter alertes antivirus.
Problèmes courants et comment les éviter
Faux positifs antivirus : signe ton binaire si possible, fournis un installateur signé, et teste sur une VM.
Fichiers manquants : oublie d’inclure web → l’UI ne chargera rien. Utilise --add-data.
Dépendances C++ (VC runtime) : certains modules requièrent Visual C++ Redistributable ; l’installateur peut l’inclure ou le
documenter.
Chemins dans code : évite chemins absolus ; utilise sys._MEIPASS (PyInstaller) pour charger ressources après packaging.
Exemple :
Python
Copier le code
import sys, os
if getattr(sys, "frozen", False):
base_path = sys._MEIPASS
else:
base_path = [Link](__file__)
web_path = [Link](base_path, "web")
Test sur autre PC : TOUJOURS tester sur un PC sans Python installé.
Recommandation pour ton cas (logiciel de caisse + site existant)
Si tu veux garder exactement le même style et réutiliser ton HTML/CSS/JS → Eel ou PyWebview + PyInstaller est le plus
rapide et simple.
Si tu veux un produit professionnel et lourd (installateur, mises à jour, auto-update) → Electron + python backend (avec
electron-builder) donnera le résultat le plus fiable côté rendu, mais demandera plus de boulot.
Utilise PyInstaller pour générer le .exe du backend Python. Ensuite, tu peux :
Emballer tout dans un seul exe (Eel/PyWebview), ou
Créer un installateur (Inno Setup) pour une installation plus propre et inclure fichiers dépendants.
Exemple concret minimal (Eel + PyInstaller)
[Link] (exemple simplifié) :
Python
Copier le code
import eel, requests, os, sys
[Link]('web')
@[Link]
def api_login(u, p):
r = [Link]("[Link] json={"username": u, "password": p})
return [Link]()
if __name__ == "__main__":
[Link]('[Link]', size=(1024, 720))
Packaging :
Bash
Copier le code
pyinstaller --noconsole --onefile --add-data "web;web" [Link]
Test : exécuter dist/[Link] sur une machine de test.