| name | pyqt-core |
| description | PyQt/PySide6 QtCore fundamentals - signals, slots, properties, timers, settings, file I/O |
| metadata | {"author":"mte90","version":"1.0.0","tags":["python","qt","pyqt","pyside","core","signals","slots"]} |
PyQt Core - QtCore Module
QtCore provides core non-GUI functionality: signals/slots, timers, settings, and file I/O.
Overview
QtCore is the foundation of Qt. It provides:
- Signal/Slot mechanism - Type-safe event handling
- Properties - Bindable object properties
- Timers - Periodic and single-shot timers
- Settings - Persistent application configuration
- File I/O - Cross-platform file operations
Signals and Slots
Signal Declaration (PySide6)
from PySide6.QtCore import QObject, Signal
class MyObject(QObject):
valueChanged = Signal(int)
nameChanged = Signal(str)
dataReady = Signal(dict)
errorOccurred = Signal(str)
positionChanged = Signal(int, int)
progressChanged = Signal(int, arguments=['percent'])
Signal Declaration (PyQt6)
from PyQt6.QtCore import QObject, pyqtSignal
class MyObject(QObject):
valueChanged = pyqtSignal(int)
nameChanged = pyqtSignal(str)
positionChanged = pyqtSignal(int, int)
Slot Declaration (PySide6)
from PySide6.QtCore import Slot
class MyObject(QObject):
@Slot()
def doSomething(self):
print("Action performed")
@Slot(int)
def setValue(self, value):
self._value = value
@Slot(str, int)
def processData(self, name, count):
pass
@Slot(result=str)
def getName(self) -> str:
return self._name
Slot Declaration (PyQt6)
from PyQt6.QtCore import pyqtSlot
class MyObject(QObject):
@pyqtSlot()
def doSomething(self):
pass
@pyqtSlot(int)
def setValue(self, value):
pass
Connecting Signals to Slots
button.clicked.connect(self.onButtonClick)
valueChanged.connect(self.updateValue)
button.clicked.connect(lambda: print("Clicked!"))
from functools import partial
button.clicked.connect(partial(self.processItem, item_id))
button.clicked.disconnect(self.onButtonClick)
is_connected = button.clicked.isConnected(self.onButtonClick)
self.valueChanged.emit(42)
self.positionChanged.emit(x, y)
button.blockSignals(True)
button.setChecked(True)
button.blockSignals(False)
count = button.receivers(button.clicked)
Connection Types
from PySide6.QtCore import Qt
button.clicked.connect(self.handleClick, Qt.AutoConnection)
button.clicked.connect(self.handleClick, Qt.DirectConnection)
worker.finished.connect(self.onFinished, Qt.QueuedConnection)
worker.result.connect(self.handleResult, Qt.BlockingQueuedConnection)
Properties
Property Declaration
from PySide6.QtCore import Property, Signal
class Person(QObject):
nameChanged = Signal()
def __init__(self):
super().__init__()
self._name = ""
@Property(str, notify=nameChanged)
def name(self):
return self._name
@name.setter
def name(self, value):
if self._name != value:
self._name = value
self.nameChanged.emit()
Using Properties
person = Person()
person.name = "Alice"
print(person.name)
person.nameChanged.connect(lambda: print("Name changed!"))
QTimer
Single-Shot Timer
from PySide6.QtCore import QTimer
QTimer.singleShot(1000, self.onTimer)
QTimer.singleShot(500, lambda: print("Delayed!"))
self.timer_id = QTimer.singleShot(1000, self.delayedAction)
Periodic Timer
from PySide6.QtCore import QTimer
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.timer = QTimer(self)
self.timer.timeout.connect(self.onTimeout)
self.timer.start(100)
def onTimeout(self):
print("Timer fired!")
def stopTimer(self):
self.timer.stop()
def isRunning(self):
return self.timer.isActive()
def remainingTime(self):
return self.timer.remainingTime()
Timer Properties
timer = QTimer()
timer.setInterval(1000)
interval = timer.interval()
timer.setSingleShot(True)
timer.setTimerType(Qt.PreciseTimer)
timer.setTimerType(Qt.CoarseTimer)
timer.setTimerType(Qt.VeryCoarseTimer)
QSettings
Basic Usage
from PySide6.QtCore import QSettings
settings = QSettings("MyCompany", "MyApp")
settings.setValue("window/geometry", self.saveGeometry())
settings.setValue("window/state", self.saveState())
settings.setValue("editor/fontSize", 12)
settings.setValue("editor/fontFamily", "Monospace")
geometry = settings.value("window/geometry")
font_size = settings.value("editor/fontSize", 10)
font_family = settings.value("editor/fontFamily", "Consolas")
if settings.contains("editor/theme"):
theme = settings.value("editor/theme")
settings.remove("editor/temp")
settings.clear()
Settings Groups
settings = QSettings("MyCompany", "MyApp")
settings.beginGroup("editor")
settings.setValue("fontSize", 12)
settings.setValue("fontFamily", "Monospace")
settings.endGroup()
settings.beginWriteArray("recentFiles")
for i, filepath in enumerate(recent_files):
settings.setArrayIndex(i)
settings.setValue("path", filepath)
settings.endArray()
size = settings.beginReadArray("recentFiles")
for i in range(size):
settings.setArrayIndex(i)
path = settings.value("path")
settings.endArray()
Settings Format
from PySide6.QtCore import QSettings
settings = QSettings("MyCompany", "MyApp")
settings = QSettings("config.ini", QSettings.IniFormat)
settings = QSettings("/path/to/settings.conf", QSettings.IniFormat)
print(settings.fileName())
File I/O
QFile
from PySide6.QtCore import QFile, QIODevice
file = QFile("data.txt")
if file.open(QIODevice.ReadOnly | QIODevice.Text):
data = file.readAll()
file.close()
print(data)
file = QFile("output.txt")
if file.open(QIODevice.WriteOnly | QIODevice.Text):
file.write(b"Hello, World!")
file.close()
file = QFile("log.txt")
if file.open(QIODevice.Append | QIODevice.Text):
file.write(b"New log entry\n")
file.close()
if QFile.exists("data.txt"):
print("File exists")
QFile.remove("temp.txt")
QFile.copy("source.txt", "dest.txt")
QFile.rename("old.txt", "new.txt")
QTextStream
from PySide6.QtCore import QFile, QTextStream, QIODevice
file = QFile("data.txt")
if file.open(QIODevice.ReadOnly | QIODevice.Text):
stream = QTextStream(file)
stream.setEncoding(QTextStream.Utf8)
content = stream.readAll()
while not stream.atEnd():
line = stream.readLine()
print(line)
file.close()
file = QFile("output.txt")
if file.open(QIODevice.WriteOnly | QIODevice.Text):
stream = QTextStream(file)
stream.setEncoding(QTextStream.Utf8)
stream << "Line 1\n"
stream << "Line 2\n"
stream.writeString("Unicode: 你好")
file.close()
QDir
from PySide6.QtCore import QDir
current = QDir.currentPath()
home = QDir.homePath()
temp = QDir.tempPath()
dir = QDir()
dir.mkpath("/path/to/new/directory")
if QDir("/path/to/dir").exists():
print("Directory exists")
dir = QDir("/path/to/dir")
entries = dir.entryList()
files = dir.entryList(QDir.Files)
dirs = dir.entryList(QDir.Dirs | QDir.NoDotAndDotDot)
entries = dir.entryList(["*.txt"], QDir.Files | QDir.Readable)
QDir("/path/to/dir").rmdir(".")
Best Practices
1. Use Type Hints
from PySide6.QtCore import Signal, Slot
class MyObject(QObject):
valueChanged = Signal(int)
@Slot(int)
def setValue(self, value: int) -> None:
self._value = value
2. Clean Up Timers
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.timer = QTimer(self)
def closeEvent(self, event):
self.timer.stop()
super().closeEvent(event)
3. Use Settings Defaults
font_size = settings.value("fontSize", 12, type=int)
theme = settings.value("theme", "dark")
4. Close Files
file = QFile("data.txt")
if file.open(QIODevice.ReadOnly):
try:
data = file.readAll()
finally:
file.close()
References