pyside-callbacks 0.1.1

Last updated:

0 purchases

pyside-callbacks 0.1.1 Image
pyside-callbacks 0.1.1 Images
Add to Cart

Description:

pysidecallbacks 0.1.1

pyside-callbacks



GitHub repository: https://github.com/schang412/pyside-callbacks
A small library that provides utility decorators for simplifying the creation of PySide6 UI. This package also contains
a mypy plugin to assist in the type-checking the signals according to the parameters.
The QT Designer workflow with Python would look like this:

Use QT Designer to create main_win.ui file.
Use uic to compile main_win.ui into main_win.py
Sub-Class the class defined in main_win.py.
Connect the signals to their handlers.

import main_win
from PySide6 import QtWidgets

class MyQtApp(main_win.Ui_MainWindow, QtWidgets.QMainWindow):
def __init__(self) -> None:
super().__init__()
self.setupUi(self)
self.pushButton.clicked.connect(self.line_edit_return_pressed)
self.lineEdit.returnPressed.connect(self.line_edit_return_pressed)

def line_edit_return_pressed(self) -> None:
cmd = self.lineEdit.text()
if not cmd:
return
self.lineEdit.setText("")
self.display.appendPlainText(cmd)

However, this connection method does not inherently offer type-checking and could be improved using decorators:
import main_win
from PySide6 import QtWidgets

import pyside_callbacks


@pyside_callbacks.pyside_callbacks
class MyQtApp(main_win.Ui_MainWindow, QtWidgets.QMainWindow):
def __init__(self) -> None:
super().__init__()
self.setupUi(self)

@pyside_callbacks.widget_event("pushButton", "clicked")
@pyside_callbacks.widget_event("lineEdit", "returnPressed")
def line_edit_return_pressed(self) -> None:
cmd = self.lineEdit.text()
if not cmd:
return
self.lineEdit.setText("")
self.display.appendPlainText(cmd)


Note that we need to decorate both the class and the method because we need to add a hook to the __init__ method in order to
register the callback to the class instance. The way that we keep track of the callbacks requires that the widget_event decorator
is the outermost decorator. However, currently, the mypy plugin expects only widget_event callbacks on functions that use it.
In other words, we cannot mix @widget_event with other decorators (for example, @staticmethod).

We can also include a mypy plugin to ensure that our signals are correct. We add the pyside_callbacks_mypy plugin and suppress the errors from the uic generated file.
[tool.mypy]
plugins = [
"pyside_callbacks_mypy.plugin"
]
[[tool.mypy.overrides]]
module = "main_win"
ignore_errors = true

Adding the following lines to the example application:
@pyside_callbacks.widget_event("lineEdit", "cursorPositionChanged")
def curpos_changed(self, b: str) -> None:
print("changed cursor position!")

Then, running mypy we will find the errors:
example/my_app/app.py:34: error: Argument 2 to "curpos_changed" has incompatible type "str"; Emitted signal will expect type "int". [arg-type]
example/my_app/app.py:34: error: Too many arguments for "curpos_changed"; Emitted signal will supply ["int", "int"] [call-arg]
Found 2 errors in 1 file (checked 2 source files)


Note that we have to add a type-hint to main_win.Ui_MainWindow.setupUi otherwise dynamic types (typing.Any) will be inferred for all the widgets.

License:

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Customer Reviews

There are no reviews.