Reference

Layout

Guietta uses a grid layout (QGridLayout). Number of rows and columns is automatically calculated from the input. There is typically one widget per grid cell ( _ will result in an empty cell), but widgets may span multiple rows and/or columns as described below.

Syntax

To create a layout, instantiate a guietta.Gui object and pass it a series of lists. Each list corresponds to a row of widgets. All lists must have the same length.

As a special case, if a list contains a single widget, the widget will be expanded to fill the whole row. This is useful for titles and horizontal separators.

Widgets

Here is the complete widget set:

from guietta import Gui, B, E, L, HS, VS, HSeparator, VSeparator
from guietta import Yes, No, Ok, Cancel, Quit, _, ___, III

gui = Gui(

   [ '<center>A big GUI with all of Guietta''s widgets</center>'],
   [ HSeparator ],

  [ 'Label'    , 'imagelabel.jpeg' , L('another label')  , VS('slider1')],
  [  _         ,     ['button']    , B('another button') ,     III      ],
  [ '__edit__' ,  E('an edit box') , _                   ,   VSeparator ],
  [   Quit     ,        Ok         , Cancel              ,     III      ],
  [    Yes     ,        No         , _                   ,     III      ],
  [  HS('slider2'),    ___         , ___                 ,      _       ] )

gui.show()
Syntax Equivalent Qt widget Event name
_ nothing (empty layout cell) none
‘text’
L(‘text’)
QLabel(‘text’) ‘text’
‘image.jpg’
L(‘image.jpg’)
QLabel with QPixmap(‘image.jpg’) ‘image’
[‘text’]
B(‘text’)
QPushButton(‘text’) ‘text’
[‘image.jpg’]
B(‘image.jpg’)
QPushButton(QIcon(‘image.jpg’), ‘’) ‘image’
‘__name__’ QLineEdit(‘’), name set to ‘name’ ‘name’
E(‘text’) QLineEdit(‘text’) ‘text’
C(‘text’) QCheckBox(‘text’) ‘text’
R(‘text’) QRadioButton(‘text’) ‘text’
P(‘name’) QProgressBar() ‘name’
PW(‘name’) QLineEdit() passsword-style (text is replaced with circles) ‘name’
G(‘title’) QGroupBox(‘title’) ‘title’
HS(‘name’) QSlider(Qt::Horizontal) ‘name’
VS(‘name’) QSlider(Qt::Horizontal) ‘name’
HSeparator Horizontal separator  
VSeparator Vertical separator  
M(‘name’) Matplotlib FigureCanvas*  
PG(‘name’) pyqtgraph PlotWidget*  
PGI(‘name’) pyqtgraph ImageView*  
widget any valid QT widget none
(widget, ‘name’) any valid QT widget ‘name’
  • Matplotlib or pyqtraph will only be imported if the M(), PG() or PGI() widgets are used. Matplotlib and pyqtgraph are not is not installed automatically together with guietta. If the M() widget is used, the user must install matplotlib manually, same for PG() and pyqtgraph.

Buttons support both images and texts at the same time:

Syntax Equivalent Qt widget Event name
[‘image.jpg’, ‘text’]
B(‘image.jpg’, ‘text’)
QPushButton() with image and text ‘text’

Continuations

How to extend widgets over multiple rows and/or columns:

from guietta import Gui, HS, VS, _, ___, III

gui = Gui(

   [ 'Big label', ___ , ___ , 'xxx' , VS('s1') ],
   [    III     , III , III , 'xxx' ,   III    ],
   [    III     , III , III , 'xxx' ,   III    ],
   [     _      ,  _  ,  _  , 'xxx' ,   III    ],
   [  HS('s2')  , ___ , ___ ,  ___  ,    _     ])
Syntax Meaning
_ nothing (empty layout cell)
___ (three underscores) Horizontal widget span
III (three capital letters i) vertical widget span

Rules:

  • all grid cells must contain either a widget, one of ___ or III, or _ if the cell is empty. Other values will cause a ValueError exception. Empty elements are not allowed by the Python list syntax and will cause a SyntaxError.
  • ___ can only be used to the right of a widget to extend it
  • III can only be used below a widget to extend it
  • ___ and III can be combined to form big rectangular widgets, with the widget to be extended in the top-left corner.

Signals

Signals can be connected with gui.events() where each widget has:

Syntax Meaning
_ no connection
slot reference to Python callable, using the default widget signal (if pre-defined, otherwise ValueError)
(‘textEdited’, slot) tuple(signal name, Python callable)

Table of default signals:

Widget Signal
QPushButton clicked(bool)
QLineEdit returnPressed()
QCheckBox stateChanged(int)
QRadioButton toggled())
QAbstractSlider (QSlider, QDial, QScrollBar) QProgressBar valueChanged(int)
QListWidget currentTextChanged
QComboBox textActivated

Widgets not listed in this table must be connected using the tuple syntax.

Properties

Table of properties created for each widget type:

Widget Read property type Write property type
QLabel, QLineEdit QGroupBox str str
QAbstractButton (QPushButton, QCheckBox, QRadioButton) widget instance callable
QAbstractSlider (QSlider, QDial, QScrollBar) QProgressBar int int
QAbstractItemView (QListWidget) list of str list of str
QComboBox dict{str: any} dict{str: any}
Matplotlib widgets widget instance 1d and 2d array-like
Everything else widget instance raises an exception

All write properties accept a guietta.Gui instance. For all widgets except QGroupBox, such a write will cause the widget to be replaced by the new Gui’s main QWidget, while the original widget will be hidden using hide(). For QGroupBox, its setLayout() method will be called using the new Gui layout as the argument.

Exception catching in slots

When a slot is called, they will be enclosed in a “try - except Exception” block. What happens in the except clause depends on the “exceptions” keyword parameter of the GUI constructor, which accepts the following enums:

Enum Exception handling
Exceptions.OFF nothing, exception is re-raised
Exceptions.POPUP (default) popup a QMessageBox.warning with the exception string
Exceptions.PRINT exception string printed on stdout
Exceptions.SILENT nothing, exception is “swallowed”

QT symbols in Guietta

List of QT symbols defined in guietta. These symbols can be imported like from guietta import x instead of importing from PySde2:

from PySide2.QtWidgets import QApplication, QLabel, QWidget, QAbstractSlider
from PySide2.QtWidgets import QPushButton, QRadioButton, QCheckBox, QFrame
from PySide2.QtWidgets import QLineEdit, QGridLayout, QSlider, QAbstractButton
from PySide2.QtWidgets import QMessageBox, QListWidget, QAbstractItemView
from PySide2.QtWidgets import QPlainTextEdit, QHBoxLayout, QComboBox
from PySide2.QtWidgets import QSplashScreen, QFileDialog, QButtonGroup
from PySide2.QtWidgets import QProgressBar, QGroupBox
from PySide2.QtGui import QPixmap, QIcon, QFont
from PySide2.QtCore import Qt, QTimer, Signal, QEvent

Gui class reference

class guietta.Gui(*lists, images_dir='.', create_properties=True, exceptions=<Exceptions.POPUP: 3>, persistence=1, title='', font=None, manage_threads=True)

Main GUI class.

The GUI is defined passing to the initializer a set of QT widgets organized in rows of equal length. All other methods that expect lists (like events() or names()) will expect a series of list with the same length.

Every widget will be added as an attribute to this instance, using the widget text as the attribute name (removing all special characters and only keeping letters, numbers and underscores.)

auto(func)

Auto-connection decorator.

Analyzes a function and auto-connects the function as a slot for all widgets that are accessed in the function itself.

close(dummy=None)

Closes the window

column_stretch(*lists)

Defines the column stretches

Arguments are lists as in the initializer. Since typically all rows have the same stretch, it is allowed to define just one or only a few rows in this method.

Every element must be a number, that will be passed to the setColumnStretch() QT function, or _ if no particular stretch is desired.

enable_drag_and_drop(from_, to)

Enable drag and drop between the two widgets

events(*lists)

Defines the GUI events.

Arguments are lists as in the initializer. It is allowed to define just one or only a few rows in this method, if for example the last rows do not contain widgets with associated events.

Every element is a tuple with:

(‘signal_name’, slot)

where ‘signal_name’ is the name of the QT signal to be connected, and slot is any Python callable. Use _ for widgets that do not need to be connected to a slot.

If just the default signal is wanted, ‘signal_name’ can be omitted and just the callable slot is required (without using a tuple).

Bound methods are called without arguments. Functions and unbound methods will get a single argument with a reference to this Gui instance.

execute_in_background(func, args=(), callback=None)

Executes func in a background thread and updates GUI with a callback.

When func is done, the callback is called in the GUI thread. The callback receives a reference to this Gui instance as the first argument, plus whatever was returned by func as additional arguments.

execute_in_main_thread(f, *args)

Make sure that f(args) is executed in the main GUI thread.

If the caller is running a different thread, the call details are packaged into a QT event that is emitted. It will be eventually received by the main thread, which will execute the call.

fonts(*lists)

Defines the fonts used for each GUI widget.

Arguments are lists as in the initializer. It is allowed to define just one or only a few rows in this method, if for example the last rows do not contain widgets whose fonts need not to be modified.

Every element is either a QFont instance, a string with a font family name (.e.g ‘Helvetica’), or a tuple with the QFont constructor elements: family string, point size, weight, and italic, int that order. All except the family string are optional, point size and weight ar integers, and italic is a boolean True/False. All these specifications are valid:

  • QFont(‘helvetica’, pointSize=12)
  • ‘helvetica’
  • (‘helvetica’, 12, 1, True)

Use _ for widgets that do not need their fonts to be changed.

get(block=True, timeout=None)

Runs the GUI in queue mode

In queue mode, no callbacks are used. Instead, the user should call gui.get() in a loop to get the events and process them. The QT event loop will stop in between calls to gui.get(), so event processing should be quick.

Every time an event happens, get() will return a tuple:

name, event = gui.get()

where name is widget name that generated the event, and event is a namedtuple with members signal (the PyQT signal) and args which is a list of signal arguments, which may be empty for signals without arguments.

get() will return (None, None) after the gui is closed.

get_selections(name)

Returns the selected items in widget name. Raises TypeError if the widget does not support selection.

import_into(obj)

Add all widgets to obj.

Adds all this Gui’s widget to obj as new attributes. Typically used in classes as an alternative from deriving from Gui. Duplicate attributes will raise an AttributeError.

iter()

Returns an interable for GUI events

for name, event in gui.iter():

layout()

Returns the GUI layout, containing all the widgets

names

Read-only property with the normalized -> original mapping

proxy(name)

Returns the guietta property for the a (normalized) widget name.

A guietta property is an instance of the GuiettaProperty class, with two attributes: get() and set()

rename(*lists)

Overrides the default widget names.

Arguments are lists as in the initializer. It is allowed to define just one or only a few rows in this method, if for example the last rows do not contain widgets that must be renamed.

Every element is a string with the new name for the widget in that position. Use _ for widgets that do not need to be renamed.

row_stretch(*lists)

Defines the row stretches

Arguments are lists as in the initializer. Since typically all rows have the same stretch, it is allowed to define just one or only a few rows in this method.

Every element in the lists must be a number, that will be passed to the setRowStretch() QT function, or _ if no particular stretch is desired.

run()

Display the Gui and start the event loop.

This call is blocking and will return when the window is closed. Any user interaction must be done with callbacks.

show()

Shows the GUI. This call is non-blocking

timer_start(callback, interval=1.0)

Set up a timer to call callback every interval seconds.

title(title)

Sets the window title

widgets

Read-only property with the widgets dictionary

window()

Returns the window containing the GUI (an instance of QWidget). If the window had not been built before, it will be now.

class guietta.GuiettaProperty(get, set, widget, add_decorators=True)

Holds the get/set methods for a Guietta magic property.

Initialize with two callables, get and set():

get() - returns the property value
set(x) - sets the property to x

widget must be a reference to the widget for which the property is being set.

The set() method is automatically decorated with guietta.execute_in_main_thread and guietta.undo_context_manager. Set add_decorators to False to avoid this. In this case, the widget parameter is ignored.

Module-level functions reference

guietta.normalized(name)

Returns the given name without any special characters or spaces.

Only a-zA-Z0-9 and _ will be kept

guietta.splash(text, textalign=<PySide2.QtCore.Qt.Alignment object>, width=None, height=None, color=PySide2.QtCore.Qt.GlobalColor.lightGray, image=None)

Display and return a splash screen.

This function displays a splashscreen and returns a QSplashScreen instance.

The splashscreen must be closed with close() or finish(gui.window()). Alternatively, it will close when the user clicks on it.

guietta.Ax(widget)

Context manager to help drawing on Matplotlib widgets.

Takes care of clearing and redrawing the canvas before and after the inner code block is executed:

with Ax(gui.plot) as ax:
    ax.plot(...)
guietta.M(name, width=5, height=3, dpi=100, subplots=(1, 1), **kwargs)

A Matplotlib Canvas widget

The **kwargs accepts additional keywords that will become function calls every time the Ax decorator is used. For example, adding the argument set_ylabel='foo', will result in this function call: ax.set_ylabel('foo')

Creating an object of this class will import the matplotlib module.

guietta.PG(name, **kwargs)

A pyqtgraph PlotWidget.

Creating an object of this class will import the pyqtgraph module.

guietta.PGI(name, **kwargs)

A pyqtgraph ImageView.

Creating an object of this class will import the pyqtgraph module.

guietta.execute_in_main_thread(gui)

Decorator that makes sure that GUI methods run in the main thread.

QT restricts GUI updates to the main thread (that is, the thread that created the GUI). In order to allow updating the GUI from other threads, any function that does so can be decorated:

@execute_in_main_thread(gui)
def myfunc(gui, widget, text):
   widget.setText(text)

The decorator checks the current thread and, if different from the main GUI thread, wraps the function call into a QT event that will be eventually received and processed by the main GUI thread. Otherwise, the function is executed immediately.

All guietta magic properties already use this decorator, so all GUI updates are automatically executed in the main GUI thread.

guietta.undo_context_manager(get_func)

Modify the decorated function so that it returns a context manager that, when exiting, restores the previous widget state (saved calling get_func):

def get_label()
    return gui.label

@undo_context_manager(get_label):
def set_label(value):
    gui.label = value

then later in the program:

with set_label(value):
    ...

upon exiting the with block, the label text will revert to its previous value.