bec-widgets 0.61.0__py3-none-any.whl → 0.62.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CHANGELOG.md +11 -9
- PKG-INFO +1 -1
- bec_widgets/cli/client_utils.py +62 -34
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +6 -5
- bec_widgets/utils/bec_dispatcher.py +5 -1
- {bec_widgets-0.61.0.dist-info → bec_widgets-0.62.0.dist-info}/METADATA +1 -1
- {bec_widgets-0.61.0.dist-info → bec_widgets-0.62.0.dist-info}/RECORD +12 -12
- docs/user/customisation.md +111 -1
- pyproject.toml +1 -1
- {bec_widgets-0.61.0.dist-info → bec_widgets-0.62.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.61.0.dist-info → bec_widgets-0.62.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-0.61.0.dist-info → bec_widgets-0.62.0.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md
CHANGED
@@ -2,6 +2,17 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
+
## v0.62.0 (2024-06-12)
|
6
|
+
|
7
|
+
### Feature
|
8
|
+
|
9
|
+
* feat: implement non-polling, interruptible waiting of gui instruction response with timeout ([`abc6caa`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/abc6caa2d0b6141dfbe1f3d025f78ae14deddcb3))
|
10
|
+
|
11
|
+
### Unknown
|
12
|
+
|
13
|
+
* doc: add documentation about creating custom GUI applications embedding BEC Widgets ([`17a0068`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/17a00687579f5efab1990cd83862ec0e78198633))
|
14
|
+
|
15
|
+
|
5
16
|
## v0.61.0 (2024-06-12)
|
6
17
|
|
7
18
|
### Feature
|
@@ -152,12 +163,3 @@
|
|
152
163
|
### Fix
|
153
164
|
|
154
165
|
* fix(docks): set_title do update dock internal _name now ([`15cbc21`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/15cbc21e5bb3cf85f5822d44a2b3665b5aa2f346))
|
155
|
-
|
156
|
-
* fix(docks): docks widget_list adn dockarea panels return values fixed ([`ffae5ee`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ffae5ee54e6b43da660131092452adff195ba4fb))
|
157
|
-
|
158
|
-
|
159
|
-
## v0.57.3 (2024-06-06)
|
160
|
-
|
161
|
-
### Documentation
|
162
|
-
|
163
|
-
* docs(bar): docs updated ([`4be0d14`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4be0d14b7445c2322c2aef86257db168a841265c))
|
PKG-INFO
CHANGED
bec_widgets/cli/client_utils.py
CHANGED
@@ -14,7 +14,7 @@ from typing import TYPE_CHECKING
|
|
14
14
|
|
15
15
|
from bec_lib.endpoints import MessageEndpoints
|
16
16
|
from bec_lib.utils.import_utils import isinstance_based_on_class_name, lazy_import, lazy_import_from
|
17
|
-
from qtpy.QtCore import
|
17
|
+
from qtpy.QtCore import QEventLoop, QSocketNotifier, QTimer
|
18
18
|
|
19
19
|
import bec_widgets.cli.client as client
|
20
20
|
from bec_widgets.cli.auto_updates import AutoUpdates
|
@@ -24,6 +24,8 @@ if TYPE_CHECKING:
|
|
24
24
|
|
25
25
|
from bec_widgets.cli.client import BECDockArea, BECFigure
|
26
26
|
|
27
|
+
from bec_lib.serialization import MsgpackSerialization
|
28
|
+
|
27
29
|
messages = lazy_import("bec_lib.messages")
|
28
30
|
# from bec_lib.connector import MessageObject
|
29
31
|
MessageObject = lazy_import_from("bec_lib.connector", ("MessageObject",))
|
@@ -205,6 +207,48 @@ class RPCResponseTimeoutError(Exception):
|
|
205
207
|
)
|
206
208
|
|
207
209
|
|
210
|
+
class QtRedisMessageWaiter:
|
211
|
+
def __init__(self, redis_connector, message_to_wait):
|
212
|
+
self.ev_loop = QEventLoop()
|
213
|
+
self.response = None
|
214
|
+
self.connector = redis_connector
|
215
|
+
self.message_to_wait = message_to_wait
|
216
|
+
self.pubsub = redis_connector._redis_conn.pubsub()
|
217
|
+
self.pubsub.subscribe(self.message_to_wait.endpoint)
|
218
|
+
fd = self.pubsub.connection._sock.fileno()
|
219
|
+
self.notifier = QSocketNotifier(fd, QSocketNotifier.Read)
|
220
|
+
self.notifier.activated.connect(self._pubsub_readable)
|
221
|
+
|
222
|
+
def _msg_received(self, msg_obj):
|
223
|
+
self.response = msg_obj.value
|
224
|
+
self.ev_loop.quit()
|
225
|
+
|
226
|
+
def wait(self, timeout=1):
|
227
|
+
timer = QTimer()
|
228
|
+
timer.singleShot(timeout * 1000, self.ev_loop.quit)
|
229
|
+
self.ev_loop.exec_()
|
230
|
+
timer.stop()
|
231
|
+
self.notifier.setEnabled(False)
|
232
|
+
self.pubsub.close()
|
233
|
+
return self.response
|
234
|
+
|
235
|
+
def _pubsub_readable(self, fd):
|
236
|
+
while True:
|
237
|
+
msg = self.pubsub.get_message()
|
238
|
+
if msg:
|
239
|
+
if msg["type"] == "subscribe":
|
240
|
+
# get_message buffers, so we may already have the answer
|
241
|
+
# let's check...
|
242
|
+
continue
|
243
|
+
else:
|
244
|
+
break
|
245
|
+
else:
|
246
|
+
return
|
247
|
+
channel = msg["channel"].decode()
|
248
|
+
msg = MessageObject(topic=channel, value=MsgpackSerialization.loads(msg["data"]))
|
249
|
+
self.connector._execute_callback(self._msg_received, msg, {})
|
250
|
+
|
251
|
+
|
208
252
|
class RPCBase:
|
209
253
|
def __init__(self, gui_id: str = None, config: dict = None, parent=None) -> None:
|
210
254
|
self._client = BECDispatcher().client
|
@@ -231,7 +275,7 @@ class RPCBase:
|
|
231
275
|
parent = parent._parent
|
232
276
|
return parent
|
233
277
|
|
234
|
-
def _run_rpc(self, method, *args, wait_for_rpc_response=True, **kwargs):
|
278
|
+
def _run_rpc(self, method, *args, wait_for_rpc_response=True, timeout=3, **kwargs):
|
235
279
|
"""
|
236
280
|
Run the RPC call.
|
237
281
|
|
@@ -253,16 +297,24 @@ class RPCBase:
|
|
253
297
|
|
254
298
|
# pylint: disable=protected-access
|
255
299
|
receiver = self._root._gui_id
|
300
|
+
if wait_for_rpc_response:
|
301
|
+
redis_msg = QtRedisMessageWaiter(
|
302
|
+
self._client.connector, MessageEndpoints.gui_instruction_response(request_id)
|
303
|
+
)
|
304
|
+
|
256
305
|
self._client.connector.set_and_publish(MessageEndpoints.gui_instructions(receiver), rpc_msg)
|
257
306
|
|
258
|
-
if
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
307
|
+
if wait_for_rpc_response:
|
308
|
+
response = redis_msg.wait(timeout)
|
309
|
+
|
310
|
+
if response is None:
|
311
|
+
raise RPCResponseTimeoutError(request_id, timeout)
|
312
|
+
|
313
|
+
# get class name
|
314
|
+
if not response.accepted:
|
315
|
+
raise ValueError(response.message["error"])
|
316
|
+
msg_result = response.message.get("result")
|
317
|
+
return self._create_widget_from_msg_result(msg_result)
|
266
318
|
|
267
319
|
def _create_widget_from_msg_result(self, msg_result):
|
268
320
|
if msg_result is None:
|
@@ -285,30 +337,6 @@ class RPCBase:
|
|
285
337
|
return cls(parent=self, **msg_result)
|
286
338
|
return msg_result
|
287
339
|
|
288
|
-
def _wait_for_response(self, request_id: str, timeout: int = 5):
|
289
|
-
"""
|
290
|
-
Wait for the response from the server.
|
291
|
-
|
292
|
-
Args:
|
293
|
-
request_id(str): The request ID.
|
294
|
-
timeout(int): The timeout in seconds.
|
295
|
-
|
296
|
-
Returns:
|
297
|
-
The response from the server.
|
298
|
-
"""
|
299
|
-
start_time = time.time()
|
300
|
-
response = None
|
301
|
-
|
302
|
-
while response is None and self.gui_is_alive() and (time.time() - start_time) < timeout:
|
303
|
-
response = self._client.connector.get(
|
304
|
-
MessageEndpoints.gui_instruction_response(request_id)
|
305
|
-
)
|
306
|
-
QCoreApplication.processEvents() # keep UI responsive (and execute signals/slots)
|
307
|
-
if response is None and (time.time() - start_time) >= timeout:
|
308
|
-
raise RPCResponseTimeoutError(request_id, timeout)
|
309
|
-
|
310
|
-
return response
|
311
|
-
|
312
340
|
def gui_is_alive(self):
|
313
341
|
"""
|
314
342
|
Check if the GUI is alive.
|
@@ -136,17 +136,18 @@ if __name__ == "__main__": # pragma: no cover
|
|
136
136
|
|
137
137
|
module_path = os.path.dirname(bec_widgets.__file__)
|
138
138
|
|
139
|
-
bec_dispatcher = BECDispatcher()
|
140
|
-
client = bec_dispatcher.client
|
141
|
-
client.start()
|
142
|
-
|
143
139
|
app = QApplication(sys.argv)
|
144
140
|
app.setApplicationName("Jupyter Console")
|
145
141
|
app.setApplicationDisplayName("Jupyter Console")
|
146
|
-
|
142
|
+
qdarktheme.setup_theme("auto")
|
147
143
|
icon = QIcon()
|
148
144
|
icon.addFile(os.path.join(module_path, "assets", "terminal_icon.png"), size=QSize(48, 48))
|
149
145
|
app.setWindowIcon(icon)
|
146
|
+
|
147
|
+
bec_dispatcher = BECDispatcher()
|
148
|
+
client = bec_dispatcher.client
|
149
|
+
client.start()
|
150
|
+
|
150
151
|
win = JupyterConsoleWindow()
|
151
152
|
win.show()
|
152
153
|
|
@@ -9,7 +9,7 @@ import redis
|
|
9
9
|
from bec_lib.client import BECClient
|
10
10
|
from bec_lib.redis_connector import MessageObject, RedisConnector
|
11
11
|
from bec_lib.service_config import ServiceConfig
|
12
|
-
from qtpy.QtCore import QObject
|
12
|
+
from qtpy.QtCore import QCoreApplication, QObject
|
13
13
|
from qtpy.QtCore import Signal as pyqtSignal
|
14
14
|
|
15
15
|
if TYPE_CHECKING:
|
@@ -71,6 +71,7 @@ class BECDispatcher:
|
|
71
71
|
|
72
72
|
_instance = None
|
73
73
|
_initialized = False
|
74
|
+
qapp = None
|
74
75
|
|
75
76
|
def __new__(cls, client=None, config: str = None, *args, **kwargs):
|
76
77
|
if cls._instance is None:
|
@@ -82,6 +83,9 @@ class BECDispatcher:
|
|
82
83
|
if self._initialized:
|
83
84
|
return
|
84
85
|
|
86
|
+
if not QCoreApplication.instance():
|
87
|
+
BECDispatcher.qapp = QCoreApplication([])
|
88
|
+
|
85
89
|
self._slots = collections.defaultdict(set)
|
86
90
|
self.client = client
|
87
91
|
|
@@ -2,11 +2,11 @@
|
|
2
2
|
.gitlab-ci.yml,sha256=3PU2LONUl10zIOD4UCPQgA6vVBtniabww1MQkTMce7I,7995
|
3
3
|
.pylintrc,sha256=OstrgmEyP0smNFBKoIN5_26-UmNZgMHnbjvAWX0UrLs,18535
|
4
4
|
.readthedocs.yaml,sha256=aSOc277LqXcsTI6lgvm_JY80lMlr69GbPKgivua2cS0,603
|
5
|
-
CHANGELOG.md,sha256=
|
5
|
+
CHANGELOG.md,sha256=TUs5Jd_fGHQ6IUvMRmlJlJZTW3dBC8hTsnJ-D8_lzdo,6881
|
6
6
|
LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
|
7
|
-
PKG-INFO,sha256=
|
7
|
+
PKG-INFO,sha256=QoubvfbHPjKGZLAQaC7bj2h7AdPFa8rk6Jj4dMgQ--o,1302
|
8
8
|
README.md,sha256=y4jB6wvArS7N8_iTbKWnSM_oRAqLA2GqgzUR-FMh5sU,2645
|
9
|
-
pyproject.toml,sha256=
|
9
|
+
pyproject.toml,sha256=p5YYYOClz-NdVPtwURPrkDjO6EJmjEOt8H-axu7tyvc,2115
|
10
10
|
.git_hooks/pre-commit,sha256=n3RofIZHJl8zfJJIUomcMyYGFi_rwq4CC19z0snz3FI,286
|
11
11
|
.gitlab/issue_templates/bug_report_template.md,sha256=gAuyEwl7XlnebBrkiJ9AqffSNOywmr8vygUFWKTuQeI,386
|
12
12
|
.gitlab/issue_templates/documentation_update_template.md,sha256=FHLdb3TS_D9aL4CYZCjyXSulbaW5mrN2CmwTaeLPbNw,860
|
@@ -18,21 +18,21 @@ bec_widgets/assets/terminal_icon.png,sha256=bJl7Tft4Fi2uxvuXI8o14uMHnI9eAWKSU2uf
|
|
18
18
|
bec_widgets/cli/__init__.py,sha256=d0Q6Fn44e7wFfLabDOBxpcJ1DPKWlFunGYDUBmO-4hA,22
|
19
19
|
bec_widgets/cli/auto_updates.py,sha256=DyBV3HnjMSH-cvVkYNcDiYKVf0Xut4Qy2qGQqkW47Bw,4833
|
20
20
|
bec_widgets/cli/client.py,sha256=6mzmRe_pjuz-3CoBJZkxaa05VzAmPLi_cDJ3uljmw8Y,54363
|
21
|
-
bec_widgets/cli/client_utils.py,sha256=
|
21
|
+
bec_widgets/cli/client_utils.py,sha256=z85Q0QWtBUf4A1X3ovWgOExKI8qVzIR2hE-lPWEOdpY,11645
|
22
22
|
bec_widgets/cli/generate_cli.py,sha256=DIaGz7nhwef3ebIaP4LtiUC3q7MoM1swJ_e0SgAO2jo,6901
|
23
23
|
bec_widgets/cli/rpc_register.py,sha256=QxXUZu5XNg00Yf5O3UHWOXg3-f_pzKjjoZYMOa-MOJc,2216
|
24
24
|
bec_widgets/cli/rpc_wigdet_handler.py,sha256=VRLujiICU_Gq0mO1Hr15YwjlxU7OcAzqeoM8QHqSubM,1032
|
25
25
|
bec_widgets/cli/server.py,sha256=rsj31Vsx6ayThNe4PQelQFahGjYXFZjfrNyB2fnm6Ro,5737
|
26
26
|
bec_widgets/examples/__init__.py,sha256=WWQ0cu7m8sA4Ehy-DWdTIqSISjaHsbxhsNmNrMnhDZU,202
|
27
27
|
bec_widgets/examples/jupyter_console/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
28
|
-
bec_widgets/examples/jupyter_console/jupyter_console_window.py,sha256=
|
28
|
+
bec_widgets/examples/jupyter_console/jupyter_console_window.py,sha256=AKIlwcOMBJ8UAIBEhPipc9lDwA25UmmBDEYAfC0L7kU,5338
|
29
29
|
bec_widgets/examples/jupyter_console/jupyter_console_window.ui,sha256=2A2mNTUMZBYygz8K4qWzrcjnNqZBMVyeHm26iLZVRWI,1473
|
30
30
|
bec_widgets/examples/motor_movement/__init__.py,sha256=LzPJkxLAxOsZCbXR-fRCPmeYobp7Yqds6tDxW4W1gSw,214
|
31
31
|
bec_widgets/examples/motor_movement/motor_control_compilations.py,sha256=8rpA7a2xVZTDMrx7YQIj3IJew78J1gcVMkHvloS0U_Q,9055
|
32
32
|
bec_widgets/examples/motor_movement/motor_controller.ui,sha256=83XX6NGILwntoUIghvzWnMuGf80O8khK3SduVKTAEFM,29105
|
33
33
|
bec_widgets/utils/__init__.py,sha256=B7OZ2ArjyFaGNh4XYIbk49agnYCz704ltuFSalLCjSA,481
|
34
34
|
bec_widgets/utils/bec_connector.py,sha256=RxHJNF7JjtY5pRbTMu2eQTiRXvoyJ53QuTYxHjZba38,5357
|
35
|
-
bec_widgets/utils/bec_dispatcher.py,sha256=
|
35
|
+
bec_widgets/utils/bec_dispatcher.py,sha256=3zzf7LXCWtxiroUuSdObGexuYfRoq0QY1i3hJ7GmbBE,5726
|
36
36
|
bec_widgets/utils/bec_table.py,sha256=nA2b8ukSeUfquFMAxGrUVOqdrzMoDYD6O_4EYbOG2zk,717
|
37
37
|
bec_widgets/utils/colors.py,sha256=GYSDe0ZxsJSwxvuy-yG2BH17qlf_Sjq8dhDcyp9IhBI,8532
|
38
38
|
bec_widgets/utils/container_utils.py,sha256=m3VUyAYmSWkEwApP9tBvKxPYVtc2kHw4toxIpMryJy4,1495
|
@@ -109,7 +109,7 @@ docs/assets/index_user_guide.svg,sha256=sRjKwOHVJStBYIQUFVcnfmbeXd2qAp0HYjleSp66
|
|
109
109
|
docs/assets/rocket_launch_48dp.svg,sha256=pdrPrBcKWUa5OlgWKM0B6TA6qAW7E57d7C7YW2r1OT8,1070
|
110
110
|
docs/developer/developer.md,sha256=7Z6sfkk_7BgwZ2vaX4z5_cJrs0miyeAYSGpqMbyBmOI,415
|
111
111
|
docs/introduction/introduction.md,sha256=wp7jmhkUtJnSnEnmIAZGUcau_3-5e5-FohvZb63khw4,1432
|
112
|
-
docs/user/customisation.md,sha256=
|
112
|
+
docs/user/customisation.md,sha256=MXqbljqokDXF3VhCeia1PITZe1mx1J3FfLTJ66TlaUA,3172
|
113
113
|
docs/user/user.md,sha256=uCTcjclIi6rdjYRQebko6bWFEVsjyfshsVU3BDYrC-Y,1403
|
114
114
|
docs/user/api_reference/api_reference.md,sha256=q2Imc48Rq6GcAP0R4bS3KuW5ptZZdsV4wxGJb3JJQHg,174
|
115
115
|
docs/user/applications/applications.md,sha256=yOECfaYRUEDIxF-O0duOwSJlG4f93RylrpMjbw1-8Dg,100
|
@@ -163,8 +163,8 @@ tests/unit_tests/test_configs/config_device_no_entry.yaml,sha256=hdvue9KLc_kfNzG
|
|
163
163
|
tests/unit_tests/test_configs/config_scan.yaml,sha256=vo484BbWOjA_e-h6bTjSV9k7QaQHrlAvx-z8wtY-P4E,1915
|
164
164
|
tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
165
165
|
tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
|
166
|
-
bec_widgets-0.
|
167
|
-
bec_widgets-0.
|
168
|
-
bec_widgets-0.
|
169
|
-
bec_widgets-0.
|
170
|
-
bec_widgets-0.
|
166
|
+
bec_widgets-0.62.0.dist-info/METADATA,sha256=QoubvfbHPjKGZLAQaC7bj2h7AdPFa8rk6Jj4dMgQ--o,1302
|
167
|
+
bec_widgets-0.62.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
|
168
|
+
bec_widgets-0.62.0.dist-info/entry_points.txt,sha256=80s2YKCNziN2ROUYbpDRyEmiejMf_dshmiYCdN7qNsU,70
|
169
|
+
bec_widgets-0.62.0.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
|
170
|
+
bec_widgets-0.62.0.dist-info/RECORD,,
|
docs/user/customisation.md
CHANGED
@@ -1,8 +1,118 @@
|
|
1
1
|
(user.customisation)=
|
2
2
|
# Customisation
|
3
3
|
|
4
|
-
BEC Widgets
|
4
|
+
## Leveraging BEC Widgets in custom GUI applications
|
5
5
|
|
6
|
+
BEC Widgets can be used to compose a complete Qt graphical application, along with
|
7
|
+
other QWidgets. The only requirement is to connect to BEC servers in order to get
|
8
|
+
data, or to interact with BEC components. This role is devoted to the BECDispatcher,
|
9
|
+
a singleton object which has to be instantiated **after the QApplication is created**.
|
10
|
+
|
11
|
+
A typical BEC Widgets custom application "main" entry point should follow the template
|
12
|
+
below:
|
13
|
+
|
14
|
+
```
|
15
|
+
import argparse
|
16
|
+
import sys
|
17
|
+
|
18
|
+
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
19
|
+
from qtpy.QtWidgets import QApplication
|
20
|
+
|
21
|
+
# optional command line arguments processing
|
22
|
+
parser = argparse.ArgumentParser(description="...")
|
23
|
+
parser.add_argument( ...)
|
24
|
+
...
|
25
|
+
args = parser.parse_args()
|
26
|
+
|
27
|
+
# creation of the Qt application
|
28
|
+
app = QApplication([])
|
29
|
+
|
30
|
+
# creation of BEC Dispatcher
|
31
|
+
# /!\ important: after the QApplication has been instantiated
|
32
|
+
bec_dispatcher = BECDispatcher()
|
33
|
+
client = bec_dispatcher.client
|
34
|
+
client.start()
|
35
|
+
|
36
|
+
# (optional) processing of command line args,
|
37
|
+
# creation of a main window depending on the command line arguments (or not)
|
38
|
+
if args.xxx == "...":
|
39
|
+
window = ...
|
40
|
+
|
41
|
+
# display of the main window and start of Qt event loop
|
42
|
+
window.show()
|
43
|
+
sys.exit(app.exec())
|
44
|
+
```
|
45
|
+
|
46
|
+
The main "window" object presents the layout of widgets to the user and allows
|
47
|
+
users to interact. BEC Widgets must be placed in the window:
|
48
|
+
|
49
|
+
```
|
50
|
+
from qtpy.QWidgets import QMainWindow
|
51
|
+
from bec_widgets.widgets import BECFigure
|
52
|
+
|
53
|
+
window = QMainWindow()
|
54
|
+
bec_figure = BECFigure(gui_id="my_gui_app_id")
|
55
|
+
window.setCentralWidget(bec_figure)
|
56
|
+
|
57
|
+
# prepare to plot samx motor vs bpm4i value
|
58
|
+
bec_figure.plot(x_name="samx", y_name="bpm4i")
|
59
|
+
```
|
60
|
+
|
61
|
+
In the example just above, the resulting application will show a plot of samx
|
62
|
+
positions on the horizontal axis, and beam intensity on the vertical axis
|
63
|
+
(when the next scan will be started).
|
64
|
+
|
65
|
+
It is important to ensure proper cleanup of the resources is done when application
|
66
|
+
quits:
|
67
|
+
|
68
|
+
```
|
69
|
+
def final_cleanup():
|
70
|
+
bec_figure.clear_all()
|
71
|
+
bec_figure.client.shutdown()
|
72
|
+
|
73
|
+
window.aboutToQuit.connect(final_cleanup)
|
74
|
+
```
|
75
|
+
|
76
|
+
Final example:
|
77
|
+
|
78
|
+
```
|
79
|
+
import sys
|
80
|
+
from qtpy.QtWidgets import QMainWindow, QApplication
|
81
|
+
from bec_widgets.widgets import BECFigure
|
82
|
+
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
83
|
+
|
84
|
+
# creation of the Qt application
|
85
|
+
app = QApplication([])
|
86
|
+
|
87
|
+
# creation of BEC Dispatcher
|
88
|
+
bec_dispatcher = BECDispatcher()
|
89
|
+
client = bec_dispatcher.client
|
90
|
+
client.start()
|
91
|
+
|
92
|
+
# creation of main window
|
93
|
+
window = QMainWindow()
|
94
|
+
|
95
|
+
# inserting BEC Widgets
|
96
|
+
bec_figure = BECFigure(parent=window, gui_id="my_gui_app_id")
|
97
|
+
window.setCentralWidget(bec_figure)
|
98
|
+
|
99
|
+
bec_figure.plot(x_name="samx", y_name="bpm4i")
|
100
|
+
|
101
|
+
# ensuring proper cleanup
|
102
|
+
def final_cleanup():
|
103
|
+
bec_figure.clear_all()
|
104
|
+
bec_figure.client.shutdown()
|
105
|
+
|
106
|
+
app.aboutToQuit.connect(final_cleanup)
|
107
|
+
|
108
|
+
# execution
|
109
|
+
window.show()
|
110
|
+
sys.exit(app.exec())
|
111
|
+
```
|
112
|
+
|
113
|
+
## Writing applications using Qt Designer
|
114
|
+
|
115
|
+
BEC Widgets are designed to be used with QtDesigner to quickly design GUI.
|
6
116
|
|
7
117
|
## Example of promoting widgets in Qt Designer
|
8
118
|
|
pyproject.toml
CHANGED
File without changes
|
File without changes
|
File without changes
|