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 anamedtuple
with memberssignal
(the PyQT signal) andargs
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
andguietta.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.