QTrio - a library bringing Qt GUIs together with async
and await
via Trio¶
Resources¶
Introduction¶
- Note:
This library is in early development. It works. It has tests. It has documentation. Expect breaking changes as we explore a clean API. By paying this price you get the privilege to provide feedback via GitHub issues to help shape our future.
:]
The QTrio project’s goal is to bring the friendly concurrency of Trio using Python’s
async
and await
syntax together with the GUI features of Qt to enable more
correct code and a more pleasant developer experience. QTrio is permissively licensed to avoid introducing
restrictions beyond those of the underlying Python Qt library you choose. Both PySide2
and PyQt5 are supported.
By enabling use of async
and await
it is possible in some cases to write related
code more concisely and clearly than you would get with the signal and slot mechanisms
of Qt concurrency. See the README
examples in the docs for the full code. The
first example here shows classic pure Qt code.
class Main:
def __init__(
self,
input_dialog: typing.Optional[QtWidgets.QInputDialog] = None,
output_dialog: typing.Optional[QtWidgets.QMessageBox] = None,
):
if input_dialog is None: # pragma: nocover
input_dialog = create_input()
if output_dialog is None: # pragma: nocover
output_dialog = create_output()
self.input_dialog = input_dialog
self.output_dialog = output_dialog
def setup(self) -> None:
self.input_dialog.accepted.connect(self.input_accepted)
self.input_dialog.rejected.connect(self.input_rejected)
self.input_dialog.show()
def input_accepted(self) -> None:
name = self.input_dialog.textValue()
self.output_dialog.setText(f"Hi {name}, welcome to the team!")
self.output_dialog.finished.connect(self.output_finished)
self.output_dialog.show()
def input_rejected(self) -> None:
QtCore.QCoreApplication.instance().quit()
def output_finished(self) -> None:
QtCore.QCoreApplication.instance().quit()
The second example, below, shows how using async
and await
allows for a
more concise and clear description of the sequenced activity.
async def main(
input_dialog: typing.Optional[qtrio.dialogs.TextInputDialog] = None,
output_dialog: typing.Optional[qtrio.dialogs.MessageBox] = None,
) -> None:
if input_dialog is None: # pragma: nocover
input_dialog = create_input()
if output_dialog is None: # pragma: nocover
output_dialog = create_output()
with contextlib.suppress(qtrio.UserCancelledError):
name = await input_dialog.wait()
output_dialog.text = f"Hi {name}, welcome to the team!"
await output_dialog.wait()