qt-debugging
SKILL.md
Qt Debugging
Diagnostic Approach
- Read the full Qt warning output — Qt prints actionable warnings before crashes
- Categorize the failure type (see categories below)
- Isolate — reproduce with a minimal test case
- Fix and verify with
QT_QPA_PLATFORM=offscreen pytest
Enabling Verbose Qt Output
# Show all Qt debug/warning messages
QT_LOGGING_RULES="*.debug=true" python -m myapp
# Filter to specific categories
QT_LOGGING_RULES="qt.qpa.*=true;qt.widgets.*=true" python -m myapp
# C++
qputenv("QT_LOGGING_RULES", "*.debug=true");
# Python: install message handler to capture Qt output
from PySide6.QtCore import qInstallMessageHandler, QtMsgType
def qt_message_handler(mode: QtMsgType, context, message: str) -> None:
if mode == QtMsgType.QtCriticalMsg or mode == QtMsgType.QtFatalMsg:
import traceback
traceback.print_stack()
print(f"Qt [{mode.name}]: {message}")
qInstallMessageHandler(qt_message_handler)
Common Failure Categories
Widget Never Appears
show()not called on top-level widget- Parent widget not shown (child inherits visibility)
setFixedSize(0, 0)or zero content margins collapsing it- Widget created after
app.exec()returns (after event loop exits) setVisible(False)still in effect
# Diagnostic
print(widget.isVisible(), widget.size(), widget.parentWidget())
Crash / Segfault on Widget Access
- Widget garbage-collected (Python deleted the QWidget before Qt finished with it)
- Common cause: widget stored only in a local variable, not
self._widget - Fix: always assign widgets to
selfattributes in__init__
# BAD — local variable, GC can collect it
def setup(self):
btn = QPushButton("Click") # may be deleted immediately
# GOOD
def setup(self):
self._btn = QPushButton("Click")
"QObject: Cannot create children for a parent in a different thread"
- A
QObjectwith a parent is being created in a non-main thread - Fix: create the object parentless, then use
moveToThreadordeleteLaterfor cleanup
"QPixmap: Must construct a QGuiApplication before a QPaintDevice"
QPixmap,QImage, orQIconcreated beforeQApplicationexists- Fix: move all Qt object construction after
app = QApplication(sys.argv)
"RuntimeError: Internal C++ object (QWidget) already deleted"
- Accessing a Python wrapper after Qt deleted the underlying C++ object
- Common with
deleteLater()— the deletion happens asynchronously - Fix: check
sip.isdeleted(widget)(PyQt6) or useQPointerpattern
Event Loop Frozen / UI Unresponsive
- Blocking call on main thread (I/O,
time.sleep, heavy computation) - Fix: move to
QRunnable/QThread(seeqt-threadingskill)
# Quick diagnostic: add to slow code path
from PySide6.QtCore import QCoreApplication
QCoreApplication.processEvents() # temporarily unblocks — confirms event loop is stuck
Signal Connected But Never Fires
- Verify the sender object is still alive
- Add debug connection:
signal.connect(lambda *a: print("FIRED", a)) - Check signal type signature matches —
Signal(int)will not fire if you emitSignal(str)equivalent - For C++: verify
Q_OBJECTis present and moc ran after last change
Memory / Resource Leak Detection
# Track live QObject count
from PySide6.QtCore import QObject
# No built-in — use objgraph
import objgraph
objgraph.show_most_common_types(limit=20)
objgraph.show_growth()
Useful Diagnostic Patterns
# Dump full widget tree
def dump_widget_tree(widget, indent=0):
print(" " * indent + repr(widget))
for child in widget.children():
if isinstance(child, QWidget):
dump_widget_tree(child, indent + 1)
# Check if event loop is running
from PySide6.QtCore import QEventLoop
print(QCoreApplication.instance().loopLevel()) # > 0 if exec() is running
# Force sync paint (debugging paint issues)
widget.repaint() # synchronous vs update() which defers
QSS / Style Debugging
# Print effective stylesheet for a widget
print(widget.styleSheet())
# Check if style rules are applying
# Add a unique background to isolate
widget.setStyleSheet("background: lime;") # visible indicator
# Force re-evaluation after property change
widget.style().unpolish(widget)
widget.style().polish(widget)
widget.update()
C++ Specific
// Enable ASAN for memory errors
// cmake -DCMAKE_CXX_FLAGS="-fsanitize=address" ...
// Qt debug output
qDebug() << "Widget size:" << widget->size();
qWarning() << "Unexpected state:" << state;
// Print all object properties
qDebug() << widget->metaObject()->className();
Weekly Installs
17
Repository
l3digital-net/c…-pluginsGitHub Stars
1
First Seen
Feb 27, 2026
Security Audits
Installed on
codex17
opencode16
gemini-cli16
claude-code16
github-copilot16
amp16