Skip to content

Commit 3628f67

Browse files
committed
interface building clean-up
added methods for adding several widgets and making solo groups much more cleanly + cleaned up code with them
1 parent b49b472 commit 3628f67

File tree

10 files changed

+364
-337
lines changed

10 files changed

+364
-337
lines changed

docs/res/code/interface.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ make_group
1818
**************************************
1919
.. autofunction:: napari_cellseg3d.interface::make_group
2020

21+
add_to_group
22+
**************************************
23+
.. autofunction:: napari_cellseg3d.interface::add_to_group
2124

2225
make_container
2326
**************************************

napari_cellseg3d/interface.py

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
napari_grey = "#262930" # napari background color (grey)
4747

4848

49-
def add_blank(widget, layout):
49+
def add_blank(widget, layout=None):
5050
"""
5151
Adds a space between consecutive buttons/labels in a layout when building a widget
5252
@@ -58,7 +58,8 @@ def add_blank(widget, layout):
5858
QLabel : blank label
5959
"""
6060
blank = QLabel("", widget)
61-
layout.addWidget(blank, alignment=ABS_AL)
61+
if layout is not None:
62+
layout.addWidget(blank, alignment=ABS_AL)
6263
return blank
6364

6465

@@ -201,35 +202,42 @@ def make_n_spinboxes(
201202
return boxes
202203

203204

204-
def make_group(title, L=7, T=20, R=7, B=11, solo_dict=None):
205-
"""Creates a group with a header (`title`) and content margins for top/left/right/bottom `L, T, R, B` (in pixels)
205+
def add_to_group(title, widget, layout, L=7, T=20, R=7, B=11):
206+
"""Adds a single widget to a layout as a named group with margins specified.
207+
208+
Args:
209+
title: title of the group
210+
widget: widget to add in the group
211+
layout: layout to add the group in
212+
L: left margin (in pixels)
213+
T: top margin (in pixels)
214+
R: right margin (in pixels)
215+
B: bottom margin (in pixels)
216+
217+
"""
218+
group, layout_internal = make_group(title, L, T, R, B)
219+
layout_internal.addWidget(widget)
220+
group.setLayout(layout_internal)
221+
layout.addWidget(group)
222+
223+
224+
def make_group(title, L=7, T=20, R=7, B=11):
225+
"""Creates a group widget and layout, with a header (`title`) and content margins for top/left/right/bottom `L, T, R, B` (in pixels)
206226
Group widget and layout returned will have a Fixed size policy.
207-
If solo_dict is not None, adds specified widget to specified layout and returns None.
208227
209228
Args:
210229
title (str): Title of the group
211230
L (int): left margin
212231
T (int): top margin
213232
R (int): right margin
214233
B (int): bottom margin
215-
solo_dict (dict): shortcut if only one widget is to be added to the group. Should contain "widget" (QWidget) and "layout" (Qlayout), widget will be added to layout. Defaults to None
216234
"""
217235
group = QGroupBox(title)
218236
group.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
219237
layout = QVBoxLayout()
220238
layout.setContentsMargins(L, T, R, B)
221239
layout.setSizeConstraint(QLayout.SetFixedSize)
222240

223-
if (
224-
solo_dict is not None
225-
): # use the dict to directly add a widget if it is alone in the group
226-
external_lay = solo_dict["layout"]
227-
external_wid = solo_dict["widget"]
228-
layout.addWidget(external_wid) # , alignment=LEFT_AL)
229-
group.setLayout(layout)
230-
external_lay.addWidget(group)
231-
return
232-
233241
return group, layout
234242

235243

@@ -331,6 +339,22 @@ def make_combobox(
331339
return menu
332340

333341

342+
def add_widgets(layout, widgets, alignment=LEFT_AL):
343+
"""Adds all widgets in the list to layout, with the specified alignment.
344+
If alignment is None, no alignment is set.
345+
Args:
346+
layout: layout to add widgets in
347+
widgets: list of QWidgets to add to layout
348+
alignment: any valid Qt.AlignmentFlag, see aliases at beginning of interface.py. If None, uses default of addWidget
349+
"""
350+
if alignment is None:
351+
for w in widgets:
352+
layout.addWidget(w)
353+
else:
354+
for w in widgets:
355+
layout.addWidget(w, alignment=alignment)
356+
357+
334358
def make_checkbox(
335359
title: str = None,
336360
func: callable = None,

napari_cellseg3d/model_framework.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,12 @@ def display_status_report(self):
207207
self.log.clear()
208208
elif not self.container_docked:
209209

210-
self.container_report_layout.addWidget( # DO NOT USE alignment here, it will break auto-resizing
211-
self.progress # , alignment=ui.CENTER_AL
212-
)
213-
self.container_report_layout.addWidget(
214-
self.log
215-
) # , alignment=ui.CENTER_AL
216-
self.container_report_layout.addWidget(
217-
self.btn_save_log # , alignment=ui.CENTER_AL
210+
ui.add_widgets(
211+
self.container_report_layout,
212+
[self.progress, self.log, self.btn_save_log],
213+
alignment=None,
218214
)
215+
219216
self.container_report.setLayout(self.container_report_layout)
220217

221218
report_dock = self._viewer.window.add_dock_widget(

napari_cellseg3d/plugin_convert.py

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,10 @@ def build(self):
8888
min_spacing=70,
8989
)
9090

91-
ui.make_group(
91+
ui.add_to_group(
9292
"Results",
93-
solo_dict={"widget": results_widget, "layout": layout},
93+
results_widget,
94+
layout,
9495
L=3,
9596
T=11,
9697
R=3,
@@ -108,14 +109,16 @@ def build(self):
108109
right_or_below=self.btn_label_files,
109110
left_or_above=self.lbl_label_files,
110111
min_spacing=70,
111-
),
112-
alignment=ui.LEFT_AL,
113-
)
114-
folder_group_l.addWidget(
115-
self.btn_convert_folder_instance, alignment=ui.HCENTER_AL
112+
)
116113
)
117-
folder_group_l.addWidget(
118-
self.btn_convert_folder_semantic, alignment=ui.HCENTER_AL
114+
115+
ui.add_widgets(
116+
folder_group_l,
117+
[
118+
self.btn_convert_folder_instance,
119+
self.btn_convert_folder_semantic,
120+
],
121+
ui.HCENTER_AL,
119122
)
120123

121124
folder_group_w.setLayout(folder_group_l)
@@ -127,11 +130,10 @@ def build(self):
127130
"Convert selected layer", l, t, r, b
128131
)
129132

130-
layer_group_l.addWidget(
131-
self.btn_convert_layer_instance, alignment=ui.HCENTER_AL
132-
)
133-
layer_group_l.addWidget(
134-
self.btn_convert_layer_semantic, alignment=ui.HCENTER_AL
133+
ui.add_widgets(
134+
layer_group_l,
135+
[self.btn_convert_layer_instance, self.btn_convert_layer_semantic],
136+
ui.HCENTER_AL,
135137
)
136138

137139
layer_group_w.setLayout(layer_group_l)
@@ -143,24 +145,26 @@ def build(self):
143145
"Remove small objects", l, t, r, b
144146
)
145147

146-
small_group_l.addWidget(
147-
self.small_object_thresh_choice, alignment=ui.HCENTER_AL
148-
)
149-
small_group_l.addWidget(
150-
self.btn_remove_small_layer, alignment=ui.HCENTER_AL
151-
)
152-
small_group_l.addWidget(
153-
self.btn_remove_small_folder, alignment=ui.HCENTER_AL
148+
ui.add_widgets(
149+
small_group_l,
150+
[
151+
self.small_object_thresh_choice,
152+
self.btn_remove_small_layer,
153+
self.btn_remove_small_folder,
154+
],
155+
ui.HCENTER_AL,
154156
)
155157

156158
small_group_w.setLayout(small_group_l)
157159
layout.addWidget(small_group_w)
158160
#############################################################
159-
ui.add_blank(layout=layout, widget=self)
160-
layout.addWidget(self.make_close_button())
161161

162-
ui.add_blank(layout=layout, widget=self)
163-
layout.addWidget(self.lbl_error)
162+
ui.add_widgets(layout, [
163+
ui.add_blank(self),
164+
self.make_close_button(),
165+
ui.add_blank(self),
166+
self.lbl_error
167+
])
164168

165169
ui.make_scrollable(layout, self, min_wh=[230, 400], base_wh=[230, 450])
166170

napari_cellseg3d/plugin_crop.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,21 @@ def build(self):
100100
w, layout = ui.make_container(0, 0, 1, 11)
101101

102102
data_group_w, data_group_l = ui.make_group("Data")
103-
data_group_l.addWidget(
104-
ui.combine_blocks(self.btn_image, self.lbl_image),
105-
alignment=ui.LEFT_AL,
103+
104+
ui.add_widgets(
105+
data_group_l,
106+
[
107+
ui.combine_blocks(self.btn_image, self.lbl_image),
108+
self.crop_label_choice, # whether to crop labels or no
109+
ui.combine_blocks(self.btn_label, self.lbl_label),
110+
self.file_handling_box,
111+
self.filetype_choice,
112+
],
106113
)
107-
data_group_l.addWidget(
108-
self.crop_label_choice,
109-
alignment=ui.LEFT_AL,
110-
) # whether to crop labels or no
114+
111115
self.crop_label_choice.toggle()
112116
self.toggle_label_path()
113117

114-
data_group_l.addWidget(
115-
ui.combine_blocks(self.btn_label, self.lbl_label),
116-
alignment=ui.LEFT_AL,
117-
)
118-
119-
data_group_l.addWidget(self.file_handling_box, alignment=ui.LEFT_AL)
120-
data_group_l.addWidget(self.filetype_choice, alignment=ui.LEFT_AL)
121118
self.filetype_choice.setVisible(False)
122119

123120
data_group_w.setLayout(data_group_l)
@@ -133,10 +130,18 @@ def build(self):
133130
]
134131
dim_group_w.setLayout(dim_group_l)
135132
layout.addWidget(dim_group_w)
136-
133+
#####################
134+
#####################
137135
ui.add_blank(self, layout)
138-
layout.addWidget(self.btn_start, alignment=ui.LEFT_AL)
139-
layout.addWidget(self.btn_close, alignment=ui.LEFT_AL)
136+
#####################
137+
#####################
138+
ui.add_widgets(
139+
layout,
140+
[
141+
self.btn_start,
142+
self.btn_close,
143+
],
144+
)
140145

141146
ui.make_scrollable(layout, self, min_wh=[180, 100])
142147

napari_cellseg3d/plugin_helper.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,15 @@ def __init__(self, viewer: "napari.viewer.Viewer"):
5151

5252
def build(self):
5353
vbox = QVBoxLayout()
54-
vbox.addWidget(self.btn1, alignment=ui.LEFT_AL)
55-
vbox.addWidget(self.btn2, alignment=ui.LEFT_AL)
56-
vbox.addWidget(self.btnc, alignment=ui.LEFT_AL)
54+
55+
widgets = [
56+
self.btn1,
57+
self.btn2,
58+
self.btnc,
59+
]
5760
if self.test:
58-
vbox.addWidget(self.epoch, alignment=ui.ABS_AL)
61+
widgets.append(self.epoch)
62+
ui.add_widgets(vbox, widgets)
5963
self.setLayout(vbox)
6064
# self.show()
6165
# self._viewer.window.add_dock_widget(self, name="Help/About...", area="right")

napari_cellseg3d/plugin_metrics.py

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -83,47 +83,44 @@ def build(self):
8383

8484
metrics_group_w, metrics_group_l = ui.make_group("Data")
8585

86-
self.lbl_image_files.setText("Ground truth")
87-
88-
metrics_group_l.addWidget(
86+
ui.add_widgets(metrics_group_l, [
8987
ui.combine_blocks(
9088
right_or_below=self.btn_image_files,
9189
left_or_above=self.lbl_image_files,
9290
min_spacing=70,
93-
),
94-
alignment=ui.LEFT_AL,
95-
)
96-
97-
self.lbl_label_files.setText("Prediction")
98-
99-
metrics_group_l.addWidget(
91+
), # images -> ground truth
10092
ui.combine_blocks(
10193
right_or_below=self.btn_label_files,
10294
left_or_above=self.lbl_label_files,
10395
min_spacing=70,
104-
),
105-
alignment=ui.LEFT_AL,
106-
)
96+
), # labels -> prediction
97+
])
98+
99+
self.lbl_image_files.setText("Ground truth")
100+
101+
self.lbl_label_files.setText("Prediction")
107102

108103
metrics_group_w.setLayout(metrics_group_l)
109104
############################
110105
ui.add_blank(self, self.layout)
111106
############################
112107
param_group_w, param_group_l = ui.make_group("Parameters")
113108

114-
param_group_l.addWidget(self.threshold_box)
115-
param_group_l.addWidget(self.rotate_choice)
109+
ui.add_widgets(param_group_l, [self.threshold_box, self.rotate_choice], None)
116110

117111
param_group_w.setLayout(param_group_l)
112+
##############################
113+
ui.add_widgets(
114+
self.layout,
115+
[
116+
metrics_group_w,
117+
param_group_w,
118+
self.btn_compute_dice,
119+
self.make_close_button(),
120+
self.btn_reset_plot,
121+
],
122+
)
118123

119-
self.layout.addWidget(metrics_group_w)
120-
self.layout.addWidget(param_group_w)
121-
122-
self.layout.addWidget(self.btn_compute_dice, alignment=ui.LEFT_AL)
123-
124-
self.layout.addWidget(self.make_close_button(), alignment=ui.LEFT_AL)
125-
126-
self.layout.addWidget(self.btn_reset_plot, alignment=ui.LEFT_AL)
127124
self.btn_reset_plot.setVisible(False)
128125

129126
ui.make_scrollable(self.layout, self)

0 commit comments

Comments
 (0)