Skip to content

A number of templates and tools to develop Qt GUI's with Python effectively.

License

Notifications You must be signed in to change notification settings

jcornall/eqt

 
 

Repository files navigation

eqt: Qt Elements

Tests PyPI Conda

Templates & tools to develop Qt GUIs in Python.

One use case is accepting user input while running another task asynchronously (so that the UI is still responsive).

  1. UIFormWidget: a class to help creating Qt forms programmatically, useable in QDockWidgets and QWidget
  2. FormDialog: a QDialog with a form inside with OK and Cancel buttons
  3. Worker: a class that defines a QRunnable to handle worker thread setup, signals and wrap up

Installation

Via pip/conda/mamba, i.e. any of the following:

  • python -m pip install eqt
  • conda install -c conda-forge eqt
  • mamba install -c conda-forge eqt

Examples

See the examples directory, e.g. how to launch a QDialog with a form inside using eqt's QWidget or FormDialog.

Running asynchronous tasks

To run a function in a separate thread we use a Worker which is a subclass of a QRunnable.

For the Worker to work one needs to define:

  1. the function that does what you need
  2. Optional callback methods to get the status of the thread by means of QtCore.QSignals

On initialisation of the Worker the user needs to pass the function that has to run in the thread, i.e. fn below, and additional optional positional and keyword arguments, which will be passed on to the actual function that is run in the QRunnable.

class Worker(QtCore.QRunnable):
    def __init__(self, fn, *args, **kwargs):
        self.fn = fn
        self.args = args
        self.kwargs = kwargs
        self.signals = WorkerSignals()

In practice the user will need to pass to the Worker as many parameters as there are listed in the function to be run.

result = self.fn(*self.args, **self.kwargs)

But Worker will add to the **kwargs the following QSignal.

        # Add progress callback to kwargs
        self.kwargs['progress_callback'] = self.signals.progress
        self.kwargs['message_callback'] = self.signals.message
        self.kwargs['status_callback'] = self.signals.status

Therefore it is advisable to always have **kwargs in the function fn signature so that you can access the QSignal and emit the signal required. For instance one could emit a progress by:

def fn(num_iter, **kwargs):
    progress_callback = kwargs.get('progress_callback', None)
    for i in range(num_iter):
        do_something
        if progress_callback is not None:
            progress_callback.emit( i )

Passing a signal to a Worker

This is done just after one has defined the Worker:

def handle_progress(num_iter):
    # do something with the progress
    print ("Current progress is ", num_iter)

worker = Worker(fn, 10)
worker.signals.progress.connect(handle_progress)

So, each time fn comes to progress_callback.emit( i ) the function handle_progress will be called with the parameter i of its for loop.

Signals available

The signals that are available in the Worker class are defined in WorkerSignal and are the following. Below you can also see the type of data that each signal can emit.

finished = QtCore.Signal()
error = QtCore.Signal(tuple)
result = QtCore.Signal(object)

progress = QtCore.Signal(int)
message = QtCore.Signal(str)
status = QtCore.Signal(tuple)

Read more on Qt signals and slots and on how to use them in PySide2.

Developer Contribution Guide

See CONTRIBUTING.md.

About

A number of templates and tools to develop Qt GUI's with Python effectively.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%