microeye 2.3.2__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.
- microEye/__init__.py +47 -0
- microEye/_version.py +2 -0
- microEye/analysis/__init__.py +1 -0
- microEye/analysis/checklist_dialog.py +143 -0
- microEye/analysis/cmosMaps.py +228 -0
- microEye/analysis/filters/__init__.py +9 -0
- microEye/analysis/filters/base.py +21 -0
- microEye/analysis/filters/spatial.py +338 -0
- microEye/analysis/filters/temporal.py +76 -0
- microEye/analysis/fitting/__init__.py +0 -0
- microEye/analysis/fitting/fit.py +680 -0
- microEye/analysis/fitting/nena.py +375 -0
- microEye/analysis/fitting/phasor_fit.py +90 -0
- microEye/analysis/fitting/processing.py +317 -0
- microEye/analysis/fitting/psf/__init__.py +6 -0
- microEye/analysis/fitting/psf/extract.py +1129 -0
- microEye/analysis/fitting/psf/rubost_mean.py +150 -0
- microEye/analysis/fitting/psf/spline.py +167 -0
- microEye/analysis/fitting/psf/stats/__init__.py +12 -0
- microEye/analysis/fitting/psf/stats/core.py +295 -0
- microEye/analysis/fitting/psf/stats/curve_fit.py +708 -0
- microEye/analysis/fitting/psf/stats/io.py +104 -0
- microEye/analysis/fitting/psf/stats/slope_fit.py +171 -0
- microEye/analysis/fitting/psf/temp.py +147 -0
- microEye/analysis/fitting/psf/test.py +47 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUfunctions.py +657 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUmleFit_LM.py +1336 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/CPUsplineLib.py +270 -0
- microEye/analysis/fitting/pyfit3Dcspline/CPU/__init__.py +1 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUfunctions.py +609 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_EMCCD.py +1396 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUmleFit_LM_sCMOS.py +1426 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/GPUsplineLib.py +231 -0
- microEye/analysis/fitting/pyfit3Dcspline/GPU/__init__.py +2 -0
- microEye/analysis/fitting/pyfit3Dcspline/__init__.py +10 -0
- microEye/analysis/fitting/pyfit3Dcspline/constants.py +27 -0
- microEye/analysis/fitting/pyfit3Dcspline/mainfunctions.py +903 -0
- microEye/analysis/fitting/results.py +917 -0
- microEye/analysis/fitting/results_stats.py +251 -0
- microEye/analysis/fitting/tardis.py +209 -0
- microEye/analysis/multi_viewer.py +568 -0
- microEye/analysis/processing/__init__.py +1 -0
- microEye/analysis/processing/frc.py +120 -0
- microEye/analysis/rendering/__init__.py +3 -0
- microEye/analysis/rendering/base.py +452 -0
- microEye/analysis/rendering/cloud.py +215 -0
- microEye/analysis/rendering/core.py +47 -0
- microEye/analysis/rendering/volumetric.py +198 -0
- microEye/analysis/tools/__init__.py +0 -0
- microEye/analysis/tools/kymograms.py +1079 -0
- microEye/analysis/tools/roi_selectors.py +556 -0
- microEye/analysis/utils/__init__.py +3 -0
- microEye/analysis/utils/coordinates.py +18 -0
- microEye/analysis/utils/images.py +68 -0
- microEye/analysis/utils/windows.py +19 -0
- microEye/analysis/viewer/__init__.py +3 -0
- microEye/analysis/viewer/image_options_widget.py +615 -0
- microEye/analysis/viewer/images.py +1225 -0
- microEye/analysis/viewer/layers_widget.py +415 -0
- microEye/analysis/viewer/localizations.py +1304 -0
- microEye/analysis/viewer/psf.py +1003 -0
- microEye/analysis/viewer/volume.py +456 -0
- microEye/hardware/__init__.py +3 -0
- microEye/hardware/cams/__init__.py +29 -0
- microEye/hardware/cams/camera_calibration.py +99 -0
- microEye/hardware/cams/camera_list.py +528 -0
- microEye/hardware/cams/camera_options.py +694 -0
- microEye/hardware/cams/camera_panel.py +941 -0
- microEye/hardware/cams/dummy/__init__.py +1 -0
- microEye/hardware/cams/dummy/dummy_panel.py +759 -0
- microEye/hardware/cams/jobs.py +497 -0
- microEye/hardware/cams/line_profiler.py +99 -0
- microEye/hardware/cams/linescan/IR_Cam.py +474 -0
- microEye/hardware/cams/linescan/__init__.py +1 -0
- microEye/hardware/cams/micam.py +524 -0
- microEye/hardware/cams/pco/__init__.py +58 -0
- microEye/hardware/cams/pco/enums.py +382 -0
- microEye/hardware/cams/pco/pco_cam.py +761 -0
- microEye/hardware/cams/pco/pco_panel.py +477 -0
- microEye/hardware/cams/shortcuts.py +312 -0
- microEye/hardware/cams/thorlabs/__init__.py +1 -0
- microEye/hardware/cams/thorlabs/thorlabs.py +1508 -0
- microEye/hardware/cams/thorlabs/thorlabs_panel.py +850 -0
- microEye/hardware/cams/ueye/__init__.py +1 -0
- microEye/hardware/cams/ueye/ueye_camera.py +1023 -0
- microEye/hardware/cams/ueye/ueye_panel.py +861 -0
- microEye/hardware/cams/vimba/__init__.py +1 -0
- microEye/hardware/cams/vimba/vimba_cam.py +1000 -0
- microEye/hardware/cams/vimba/vimba_panel.py +813 -0
- microEye/hardware/device.py +60 -0
- microEye/hardware/lasers/__init__.py +13 -0
- microEye/hardware/lasers/io_matchbox.py +791 -0
- microEye/hardware/lasers/io_params.py +85 -0
- microEye/hardware/lasers/io_single_laser.py +742 -0
- microEye/hardware/lasers/laser_relay.py +594 -0
- microEye/hardware/mieye/__init__.py +1 -0
- microEye/hardware/mieye/acquisition_manager.py +467 -0
- microEye/hardware/mieye/devices_manager.py +533 -0
- microEye/hardware/mieye/miEye.py +659 -0
- microEye/hardware/misc/__init__.py +0 -0
- microEye/hardware/misc/acquisition_view.py +71 -0
- microEye/hardware/misc/reglo.py +761 -0
- microEye/hardware/misc/temp.py +188 -0
- microEye/hardware/port_config.py +59 -0
- microEye/hardware/protocols/__init__.py +2 -0
- microEye/hardware/protocols/actions.py +402 -0
- microEye/hardware/protocols/actions_items.py +703 -0
- microEye/hardware/protocols/designer.py +244 -0
- microEye/hardware/protocols/scene_manager.py +191 -0
- microEye/hardware/protocols/serialization.py +97 -0
- microEye/hardware/pycromanager/__init__.py +16 -0
- microEye/hardware/pycromanager/core.py +1433 -0
- microEye/hardware/pycromanager/devices.py +461 -0
- microEye/hardware/pycromanager/enums.py +107 -0
- microEye/hardware/pycromanager/headless.py +153 -0
- microEye/hardware/pycromanager/utils.py +34 -0
- microEye/hardware/pycromanager/widgets/__init__.py +5 -0
- microEye/hardware/pycromanager/widgets/bridges.py +407 -0
- microEye/hardware/pycromanager/widgets/headless_manager.py +258 -0
- microEye/hardware/pycromanager/widgets/headless_options.py +224 -0
- microEye/hardware/pycromanager/widgets/pycro_panel.py +455 -0
- microEye/hardware/stages/__init__.py +18 -0
- microEye/hardware/stages/elliptec/__init__.py +5 -0
- microEye/hardware/stages/elliptec/baseDevice.py +314 -0
- microEye/hardware/stages/elliptec/device.py +384 -0
- microEye/hardware/stages/elliptec/deviceID.py +212 -0
- microEye/hardware/stages/elliptec/devicePort.py +379 -0
- microEye/hardware/stages/elliptec/deviceStatus.py +65 -0
- microEye/hardware/stages/elliptec/devicesView.py +706 -0
- microEye/hardware/stages/elliptec/ellDevices.py +134 -0
- microEye/hardware/stages/elliptec/messageUpdater.py +34 -0
- microEye/hardware/stages/elliptec/motorInfo.py +153 -0
- microEye/hardware/stages/elliptec/stage.py +62 -0
- microEye/hardware/stages/elliptec/test.py +139 -0
- microEye/hardware/stages/kinesis/__init__.py +1 -0
- microEye/hardware/stages/kinesis/kdc101/__init__.py +1 -0
- microEye/hardware/stages/kinesis/kdc101/enums.py +1002 -0
- microEye/hardware/stages/kinesis/kdc101/factory.py +171 -0
- microEye/hardware/stages/kinesis/kdc101/kdc101.py +718 -0
- microEye/hardware/stages/kinesis/kinesis.py +776 -0
- microEye/hardware/stages/piezo_concept.py +607 -0
- microEye/hardware/stages/stabilizer.py +785 -0
- microEye/hardware/stages/stage.py +89 -0
- microEye/hardware/widgets/__init__.py +10 -0
- microEye/hardware/widgets/controller.py +246 -0
- microEye/hardware/widgets/devices.py +133 -0
- microEye/hardware/widgets/focusWidget.py +264 -0
- microEye/hardware/widgets/qlist_slider.py +113 -0
- microEye/hardware/widgets/scan_acquisition.py +424 -0
- microEye/icons/1024.png +0 -0
- microEye/icons/128.png +0 -0
- microEye/icons/16.png +0 -0
- microEye/icons/24.png +0 -0
- microEye/icons/256.png +0 -0
- microEye/icons/32.png +0 -0
- microEye/icons/48.png +0 -0
- microEye/icons/512.png +0 -0
- microEye/icons/64.png +0 -0
- microEye/icons/__init__.py +0 -0
- microEye/icons/close.svg +88 -0
- microEye/icons/mieye.png +0 -0
- microEye/icons/min.svg +83 -0
- microEye/icons/viewer.png +0 -0
- microEye/launcher.py +42 -0
- microEye/qt.py +181 -0
- microEye/utils/__init__.py +2 -0
- microEye/utils/enum_encoder.py +10 -0
- microEye/utils/expandable_groupbox.py +93 -0
- microEye/utils/gui_helper.py +457 -0
- microEye/utils/hid/__init__.py +8 -0
- microEye/utils/hid/controller.py +153 -0
- microEye/utils/hid/device.py +63 -0
- microEye/utils/hid/enums.py +140 -0
- microEye/utils/hid/utils.py +58 -0
- microEye/utils/labelled_slider.py +134 -0
- microEye/utils/metadata.py +599 -0
- microEye/utils/metadata_tree.py +718 -0
- microEye/utils/micro_launcher.py +245 -0
- microEye/utils/parameter_tree.py +325 -0
- microEye/utils/pyscripting.py +444 -0
- microEye/utils/retry_exec.py +35 -0
- microEye/utils/start_gui.py +112 -0
- microEye/utils/thread_worker.py +115 -0
- microEye/utils/uImage.py +1512 -0
- microeye-2.3.2.dist-info/METADATA +401 -0
- microeye-2.3.2.dist-info/RECORD +190 -0
- microeye-2.3.2.dist-info/WHEEL +5 -0
- microeye-2.3.2.dist-info/entry_points.txt +2 -0
- microeye-2.3.2.dist-info/licenses/LICENSE +674 -0
- microeye-2.3.2.dist-info/top_level.txt +1 -0
microEye/qt.py
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def check_modules(modules: list[str]) -> dict[str, bool]:
|
|
5
|
+
availability = {}
|
|
6
|
+
for module in modules:
|
|
7
|
+
try:
|
|
8
|
+
__import__(module)
|
|
9
|
+
availability[module] = True
|
|
10
|
+
except ImportError:
|
|
11
|
+
availability[module] = False
|
|
12
|
+
return availability
|
|
13
|
+
|
|
14
|
+
availability = check_modules(['PySide6', 'PyQt6', 'PyQt5'])
|
|
15
|
+
|
|
16
|
+
all_false = all(not value for value in availability.values())
|
|
17
|
+
|
|
18
|
+
if all_false:
|
|
19
|
+
raise ImportError('Missing Qt packages, install one of PySide6, PyQt5, PyQt6.')
|
|
20
|
+
|
|
21
|
+
QT_API = os.environ.get('QT_API', 'PySide6')
|
|
22
|
+
|
|
23
|
+
if not availability.get(QT_API, False):
|
|
24
|
+
for key, value in availability.items():
|
|
25
|
+
if value:
|
|
26
|
+
QT_API = key
|
|
27
|
+
break
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
os.environ['QT_API'] = QT_API
|
|
31
|
+
os.environ['PYQTGRAPH_QT_LIB'] = QT_API
|
|
32
|
+
|
|
33
|
+
if QT_API == 'PySide6':
|
|
34
|
+
from PySide6 import QtCore, QtGui, QtSerialPort, QtSvg, QtWidgets
|
|
35
|
+
from PySide6.QtCore import QDateTime, Qt, Signal, Slot
|
|
36
|
+
from PySide6.QtGui import QAction, QIcon
|
|
37
|
+
from PySide6.QtWidgets import (
|
|
38
|
+
QApplication,
|
|
39
|
+
QFileSystemModel,
|
|
40
|
+
QMainWindow,
|
|
41
|
+
QVBoxLayout,
|
|
42
|
+
)
|
|
43
|
+
elif QT_API == 'PyQt5':
|
|
44
|
+
from PyQt5 import Qsci, QtCore, QtGui, QtSerialPort, QtSvg, QtWidgets
|
|
45
|
+
from PyQt5.QtCore import QDateTime, Qt
|
|
46
|
+
from PyQt5.QtCore import pyqtSignal as Signal
|
|
47
|
+
from PyQt5.QtCore import pyqtSlot as Slot
|
|
48
|
+
from PyQt5.QtGui import QIcon
|
|
49
|
+
from PyQt5.QtWidgets import QAction, QApplication, QFileSystemModel, QMainWindow
|
|
50
|
+
elif QT_API == 'PyQt6':
|
|
51
|
+
from PyQt6 import Qsci, QtCore, QtGui, QtSerialPort, QtSvg, QtWidgets
|
|
52
|
+
from PyQt6.QtCore import QDateTime, Qt
|
|
53
|
+
from PyQt6.QtCore import pyqtSignal as Signal
|
|
54
|
+
from PyQt6.QtCore import pyqtSlot as Slot
|
|
55
|
+
from PyQt6.QtGui import QAction, QFileSystemModel, QIcon
|
|
56
|
+
from PyQt6.QtWidgets import QApplication, QMainWindow
|
|
57
|
+
else:
|
|
58
|
+
raise ImportError('QT_API environment variable is not correctly set. \
|
|
59
|
+
It should be one of PySide6, PyQt5, PyQt6.')
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def checkDialogOptions(options) -> QtWidgets.QFileDialog.Option:
|
|
63
|
+
if options is None or not isinstance(options, QtWidgets.QFileDialog.Option):
|
|
64
|
+
options = QtWidgets.QFileDialog.Option(0)
|
|
65
|
+
return options
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def getOpenFileName(
|
|
69
|
+
parent: QtWidgets.QWidget = None,
|
|
70
|
+
caption='Open File',
|
|
71
|
+
directory='',
|
|
72
|
+
filter='All Files (*)',
|
|
73
|
+
initial_filter='',
|
|
74
|
+
options: QtWidgets.QFileDialog.Option =None,
|
|
75
|
+
):
|
|
76
|
+
options = checkDialogOptions(options)
|
|
77
|
+
if QT_API == 'PySide6':
|
|
78
|
+
return QtWidgets.QFileDialog.getOpenFileName(
|
|
79
|
+
parent,
|
|
80
|
+
caption,
|
|
81
|
+
dir=directory,
|
|
82
|
+
filter=filter,
|
|
83
|
+
selectedFilter=initial_filter,
|
|
84
|
+
options=options,
|
|
85
|
+
)
|
|
86
|
+
elif QT_API == 'PyQt6' or QT_API == 'PyQt5':
|
|
87
|
+
return QtWidgets.QFileDialog.getOpenFileName(
|
|
88
|
+
parent,
|
|
89
|
+
caption,
|
|
90
|
+
directory=directory,
|
|
91
|
+
filter=filter,
|
|
92
|
+
initialFilter=initial_filter,
|
|
93
|
+
options=options,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def getOpenFileNames(
|
|
98
|
+
parent: QtWidgets.QWidget = None,
|
|
99
|
+
caption='Save File',
|
|
100
|
+
directory='',
|
|
101
|
+
filter='All Files (*)',
|
|
102
|
+
initial_filter='',
|
|
103
|
+
options: QtWidgets.QFileDialog.Option =None,
|
|
104
|
+
):
|
|
105
|
+
options = checkDialogOptions(options)
|
|
106
|
+
if QT_API == 'PySide6':
|
|
107
|
+
return QtWidgets.QFileDialog.getOpenFileNames(
|
|
108
|
+
parent,
|
|
109
|
+
caption,
|
|
110
|
+
dir=directory,
|
|
111
|
+
filter=filter,
|
|
112
|
+
selectedFilter=initial_filter,
|
|
113
|
+
options=options,
|
|
114
|
+
)
|
|
115
|
+
elif QT_API == 'PyQt6' or QT_API == 'PyQt5':
|
|
116
|
+
return QtWidgets.QFileDialog.getOpenFileNames(
|
|
117
|
+
parent,
|
|
118
|
+
caption,
|
|
119
|
+
directory=directory,
|
|
120
|
+
filter=filter,
|
|
121
|
+
initialFilter=initial_filter,
|
|
122
|
+
options=options,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def getSaveFileName(
|
|
127
|
+
parent: QtWidgets.QWidget = None,
|
|
128
|
+
caption='Save File',
|
|
129
|
+
directory='',
|
|
130
|
+
filter='All Files (*)',
|
|
131
|
+
initial_filter='',
|
|
132
|
+
options: QtWidgets.QFileDialog.Option =None,
|
|
133
|
+
):
|
|
134
|
+
options = checkDialogOptions(options)
|
|
135
|
+
if QT_API == 'PySide6':
|
|
136
|
+
return QtWidgets.QFileDialog.getSaveFileName(
|
|
137
|
+
parent,
|
|
138
|
+
caption,
|
|
139
|
+
dir=directory,
|
|
140
|
+
filter=filter,
|
|
141
|
+
selectedFilter=initial_filter,
|
|
142
|
+
options=options,
|
|
143
|
+
)
|
|
144
|
+
elif QT_API == 'PyQt6' or QT_API == 'PyQt5':
|
|
145
|
+
return QtWidgets.QFileDialog.getSaveFileName(
|
|
146
|
+
parent,
|
|
147
|
+
caption,
|
|
148
|
+
directory=directory,
|
|
149
|
+
filter=filter,
|
|
150
|
+
initialFilter=initial_filter,
|
|
151
|
+
options=options,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def getExistingDirectory(
|
|
156
|
+
parent: QtWidgets.QWidget = None,
|
|
157
|
+
caption='Save File',
|
|
158
|
+
directory='',
|
|
159
|
+
filter='All Files (*)',
|
|
160
|
+
initial_filter='',
|
|
161
|
+
options: QtWidgets.QFileDialog.Option =None,
|
|
162
|
+
):
|
|
163
|
+
options = checkDialogOptions(options)
|
|
164
|
+
if QT_API == 'PySide6':
|
|
165
|
+
return QtWidgets.QFileDialog.getExistingDirectory(
|
|
166
|
+
parent,
|
|
167
|
+
caption,
|
|
168
|
+
dir=directory,
|
|
169
|
+
filter=filter,
|
|
170
|
+
selectedFilter=initial_filter,
|
|
171
|
+
options=options,
|
|
172
|
+
)
|
|
173
|
+
elif QT_API == 'PyQt6' or QT_API == 'PyQt5':
|
|
174
|
+
return QtWidgets.QFileDialog.getExistingDirectory(
|
|
175
|
+
parent,
|
|
176
|
+
caption,
|
|
177
|
+
directory=directory,
|
|
178
|
+
filter=filter,
|
|
179
|
+
initialFilter=initial_filter,
|
|
180
|
+
options=options,
|
|
181
|
+
)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from microEye.qt import QApplication, QtWidgets
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ExpandableGroupBox(QtWidgets.QGroupBox):
|
|
5
|
+
"""
|
|
6
|
+
Custom QGroupBox with expandable functionality.
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
title : str
|
|
11
|
+
The title of the group box.
|
|
12
|
+
parent : QWidget, optional
|
|
13
|
+
The parent widget.
|
|
14
|
+
|
|
15
|
+
Attributes
|
|
16
|
+
----------
|
|
17
|
+
None
|
|
18
|
+
|
|
19
|
+
Signals
|
|
20
|
+
-------
|
|
21
|
+
toggled : bool
|
|
22
|
+
Emitted when the group box is toggled (expanded or collapsed).
|
|
23
|
+
|
|
24
|
+
Methods
|
|
25
|
+
-------
|
|
26
|
+
init_ui()
|
|
27
|
+
Initialize the user interface.
|
|
28
|
+
mouseDoubleClickEvent(event)
|
|
29
|
+
Handle the mouse press event to toggle the expansion state.
|
|
30
|
+
setFlat(flat)
|
|
31
|
+
Override the setFlat method to adjust the visibility of child widgets.
|
|
32
|
+
|
|
33
|
+
Example
|
|
34
|
+
-------
|
|
35
|
+
>>> app = QApplication([])
|
|
36
|
+
>>> main_widget = QWidget()
|
|
37
|
+
>>> main_layout = QVBoxLayout(main_widget)
|
|
38
|
+
>>> expandable_group = ExpandableGroupBox('Expandable Group')
|
|
39
|
+
>>> button1 = QPushButton('Button 1')
|
|
40
|
+
>>> button2 = QPushButton('Button 2')
|
|
41
|
+
>>> expandable_group.layout().addWidget(button1)
|
|
42
|
+
>>> expandable_group.layout().addWidget(button2)
|
|
43
|
+
>>> main_layout.addWidget(expandable_group)
|
|
44
|
+
>>> main_widget.show()
|
|
45
|
+
>>> app.exec()
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, title: str, parent=None):
|
|
49
|
+
'''
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
title : str
|
|
53
|
+
The title of the group box.
|
|
54
|
+
parent : QWidget, optional
|
|
55
|
+
The parent widget.
|
|
56
|
+
'''
|
|
57
|
+
super().__init__(title, parent)
|
|
58
|
+
self.init_ui()
|
|
59
|
+
|
|
60
|
+
def init_ui(self):
|
|
61
|
+
'''Initialize the user interface.'''
|
|
62
|
+
group_layout = QtWidgets.QVBoxLayout()
|
|
63
|
+
self.setLayout(group_layout)
|
|
64
|
+
self.expanded = True
|
|
65
|
+
|
|
66
|
+
def mouseDoubleClickEvent(self, event):
|
|
67
|
+
'''Handle the mouse press event to toggle the expansion state.'''
|
|
68
|
+
self.expanded = not self.expanded
|
|
69
|
+
self.setFlat(not self.expanded)
|
|
70
|
+
# Hide or show child widgets based on the expansion state
|
|
71
|
+
for i in range(self.layout().count()):
|
|
72
|
+
item = self.layout().itemAt(i)
|
|
73
|
+
if item.widget():
|
|
74
|
+
item.widget().setVisible(self.expanded)
|
|
75
|
+
# Set the minimum height dynamically based on the expansion state
|
|
76
|
+
if self.expanded:
|
|
77
|
+
item.widget().setMinimumHeight(125)
|
|
78
|
+
else:
|
|
79
|
+
item.widget().setMinimumHeight(0)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
if __name__ == '__main__':
|
|
83
|
+
app = QApplication([])
|
|
84
|
+
main_widget = QtWidgets.QWidget()
|
|
85
|
+
main_layout = QtWidgets.QVBoxLayout(main_widget)
|
|
86
|
+
expandable_group = ExpandableGroupBox('Expandable Group')
|
|
87
|
+
button1 = QtWidgets.QPushButton('Button 1')
|
|
88
|
+
button2 = QtWidgets.QPushButton('Button 2')
|
|
89
|
+
expandable_group.layout().addWidget(button1)
|
|
90
|
+
expandable_group.layout().addWidget(button2)
|
|
91
|
+
main_layout.addWidget(expandable_group)
|
|
92
|
+
main_widget.show()
|
|
93
|
+
app.exec()
|