{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ItomUI class\n\nDemo to show how to create a user interface in an object oriented approach.\n\nThis demo uses the base class ``ItomUi`` from the module ``itomUi``. This module\nis distributed with itom and can directly be imported (located in the itom-packages\ndirectory).\n\nThe proposal is to create one class, that represents all code, that is related\nto one ui file. This class is therefore derived from ``ItomUi``.\n\nThe benefits are:\n\n1. It is possible to create member methods in your class, that are automatically\n called if the user does a specific action in the user interface (e.g. clicks\n a button). For this, the method needs to have a specific method name. Then,\n this method is considered to be a ``slot`` and is automatically connected with\n the ``signal``, that is emitted due to the action. Methods, that should be\n auto-connected slots must be decorated with the @ItomUi.autoslot decorator.\n \n2. Use the factory function ``ItomUi.disableGui`` for with statements to\n switch some items of the GUI to a specific state (disable, enable, hide, show)\n before starting a long operation and automatically switch back to the previous\n state at the end of the operation. Even if the operation fails with an unhandled\n exception, the GUI is reverted to the original state.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from itomUi import ItomUi\nfrom itom import ui\nimport time\n\n\n\nclass ItomUiClassDemo(ItomUi):\n \"\"\"This class contains the code for the user interface \"itomUiClassDemo.ui\".\"\"\"\n\n def __init__(self):\n \"\"\"Constructor.\n\n Instead of directly creating an object of the class ``itom.ui``\n call the constructor of the base class with the same arguments than\n ``itom.ui``. The ui object is then accessible by the member ``self.gui``.\n\n Use the constructor to further initialize the user interface.\n \"\"\"\n ItomUi.__init__(self, \"itomUiClassDemo.ui\", type=ui.TYPEWINDOW, deleteOnClose=True)\n\n # further initialization\n self.gui.progressBar[\"visible\"] = False\n\n @ItomUi.autoslot(\"bool\")\n def on_checkEnabled_toggled(self, checked):\n \"\"\"Auto-slot if the check box has been checked or unchecked.\n\n This method is automatically connected with the ``toggled`` signal of\n the check box with the object name ``checkEnabled`` (see QtDesigner >>\n property toolbox) since it has the ``ItomUi.autoslot`` decorator and since\n the method name follows the pattern ``on__``.\n\n The signal is the original C++ signal name of the widget (item). It can\n be obtained either from the Qt documentation or by calling the ``info`` method\n of the ``itom.uiItem``, that represents the desired widget. If the signal\n has some arguments, write a comma separated list (without separators) of the\n C++ datatypes of the arguments in the string argument of the decorator.\n\n Args:\n checked (bool): This argument is the boolean argument of\n the signal ``toggled(bool checked)`` of the checkbox (class QCheckBox).\n \"\"\"\n self.gui.groupBox[\"enabled\"] = checked\n\n @ItomUi.autoslot(\"\") # the signal is clicked()\n def on_btnStart_clicked(self):\n \"\"\"Auto-slot that is connected with the ``clicked`` signal of the button btnStart.\n\n This method emulates a long operation. During the operation, the\n group box is disabled and the progress bar of the ui is shown.\n Afterwards, both properties are reverted to their original state\n (dependent on the current enabled state of the group box).\n \"\"\"\n # the following items will be disabled (enabled=False) during with statement\n disableItems = [\n self.gui.groupBox,\n self.gui.checkEnabled,\n self.gui.btnStart,\n ]\n\n # the following items will be shown (visible=True) during with statement\n showItems = [\n self.gui.progressBar,\n ]\n\n # the following items will be hidden (visible=False) during with statement\n hideItems = [\n self.gui.btnStartException,\n ]\n\n # the following items will be enabled (enabled=True) during with statement\n enableItems = []\n\n with self.disableGui(\n disableItems=disableItems,\n showItems=showItems,\n hideItems=hideItems,\n enableItems=enableItems,\n revertToInitialStateOnExit=True,\n showWaitCursor=self.gui.checkWaitCursor[\"checked\"],\n ):\n # long going operation within the with statement\n time.sleep(3)\n\n @ItomUi.autoslot(\"\") # the signal is clicked()\n def on_btnStartException_clicked(self):\n \"\"\"Auto-slot that is connected with the ``clicked`` signal of the button btnStartException.\n\n This method emulates a long operation. During the operation, the\n group box is disabled and the progress bar of the ui is shown.\n Afterwards, both properties are reverted to their original state\n (dependent on the current enabled state of the group box).\n\n The special thing of this demo is, that an unhandled exception happens\n during the operation. Nevertheless, the GUI is turned into its previous\n state. This is a feature of the ``disableGui`` factory function for\n a with statement.\n \"\"\"\n # the following items will be disabled (enabled=False) during with statement\n disableItems = [\n self.gui.groupBox,\n self.gui.checkEnabled,\n self.gui.btnStartException,\n ]\n\n # the following items will be shown (visible=True) during with statement\n showItems = [\n self.gui.progressBar,\n ]\n\n # the following items will be hidden (visible=False) during with statement\n hideItems = [\n self.gui.btnStart,\n ]\n\n # the following items will be enabled (enabled=True) during with statement\n enableItems = []\n\n with self.disableGui(\n disableItems=disableItems,\n showItems=showItems,\n hideItems=hideItems,\n enableItems=enableItems,\n revertToInitialStateOnExit=True,\n showWaitCursor=self.gui.checkWaitCursor[\"checked\"],\n ):\n # long going operation within the with statement\n time.sleep(3)\n\n raise RuntimeError(\n \"an unhandled exception occurred, but the \" \"GUI is turned into the original state though\"\n )\n\n\nif __name__ == \"__main__\":\n win = ItomUiClassDemo()\n win.show() # this method internally calls ``itom.ui.show``." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.10" } }, "nbformat": 4, "nbformat_minor": 0 }