def _create_ui()

in utils_cv/classification/widget.py [0:0]


    def _create_ui(self):
        """Create and initialize widgets"""
        # ------------
        # Callbacks + logic
        # ------------
        def skip_image():
            """Return true if image should be skipped, and false otherwise."""
            # See if UI-checkbox to skip images is checked
            if not self.w_skip_annotated.value:
                return False

            # Stop skipping if image index is out of bounds
            if (
                self.vis_image_index <= 0
                or self.vis_image_index >= len(self.im_filenames) - 1
            ):
                return False

            # Skip if image has annotation
            im_filename = self.im_filenames[self.vis_image_index]
            labels = self.annos[im_filename].labels
            exclude = self.annos[im_filename].exclude
            if exclude or len(labels) > 0:
                return True

            return False

        def button_pressed(obj):
            """Next / previous image button callback."""
            # Find next/previous image. Variable step is -1 or +1 depending on which button was pressed.
            step = int(obj.value)
            self.vis_image_index += step
            while skip_image():
                self.vis_image_index += step

            self.vis_image_index = min(
                max(self.vis_image_index, 0), len(self.im_filenames) - 1
            )
            self.w_image_slider.value = self.vis_image_index
            self.update_ui()

        def slider_changed(obj):
            """Image slider callback.
            Need to wrap in try statement to avoid errors when slider value is not a number.
            """
            try:
                self.vis_image_index = int(obj["new"]["value"])
                self.update_ui()
            except Exception:
                pass

        def anno_changed(obj):
            """Label checkbox callback.
            Update annotation file and write to disk
            """
            # Test if call is coming from the user having clicked on a checkbox to change its state,
            # rather than a change of state when e.g. the checkbox value was updated programatically. This is a bit
            # of hack, but necessary since widgets.Checkbox() does not support a on_click() callback or similar.
            if (
                "new" in obj
                and isinstance(obj["new"], dict)
                and len(obj["new"]) == 0
            ):
                # If single-label annotation then unset all checkboxes except the one which the user just clicked
                if not self.w_multi_class.value:
                    for w in self.label_widgets:
                        if w.description != obj["owner"].description:
                            w.value = False

                # Update annotation object
                im_filename = self.im_filenames[self.vis_image_index]
                self.annos[im_filename].labels = [
                    w.description for w in self.label_widgets if w.value
                ]
                self.annos[im_filename].exclude = self.exclude_widget.value

                # Write to disk as tab-separated file.
                with open(self.anno_path, "w") as f:
                    f.write(
                        "{}\t{}\t{}\n".format(
                            "IM_FILENAME", "EXCLUDE", "LABELS"
                        )
                    )
                    for k, v in self.annos.items():
                        if v.labels != [] or v.exclude:
                            f.write(
                                "{}\t{}\t{}\n".format(
                                    k, v.exclude, ",".join(v.labels)
                                )
                            )

        # ------------
        # UI - image + controls (left side)
        # ------------
        w_next_image_button = widgets.Button(description="Next")
        w_next_image_button.value = "1"
        w_next_image_button.layout = Layout(width="80px")
        w_next_image_button.on_click(button_pressed)
        w_previous_image_button = widgets.Button(description="Previous")
        w_previous_image_button.value = "-1"
        w_previous_image_button.layout = Layout(width="80px")
        w_previous_image_button.on_click(button_pressed)

        self.w_filename = widgets.Text(
            value="", description="Name:", layout=Layout(width="200px")
        )
        self.w_path = widgets.Text(
            value="", description="Path:", layout=Layout(width="200px")
        )
        self.w_image_slider = IntSlider(
            min=0,
            max=len(self.im_filenames) - 1,
            step=1,
            value=self.vis_image_index,
            continuous_update=False,
        )
        self.w_image_slider.observe(slider_changed)
        self.w_img = widgets.Image()
        self.w_img.layout.width = f"{self.IM_WIDTH}px"

        w_header = widgets.HBox(
            children=[
                w_previous_image_button,
                w_next_image_button,
                self.w_image_slider,
                self.w_filename,
                self.w_path,
            ]
        )

        # ------------
        # UI - info (right side)
        # ------------
        # Options widgets
        self.w_skip_annotated = widgets.Checkbox(
            value=False, description="Skip annotated images."
        )
        self.w_multi_class = widgets.Checkbox(
            value=False, description="Allow multi-class labeling"
        )

        # Label checkboxes widgets
        self.exclude_widget = widgets.Checkbox(
            value=False, description="EXCLUDE IMAGE"
        )
        self.exclude_widget.observe(anno_changed)
        self.label_widgets = [
            widgets.Checkbox(value=False, description=label)
            for label in self.labels
        ]
        for label_widget in self.label_widgets:
            label_widget.observe(anno_changed)

        # Combine UIs into tab widget
        w_info = widgets.VBox(
            children=[
                widgets.HTML(value="Options:"),
                self.w_skip_annotated,
                self.w_multi_class,
                widgets.HTML(value="Annotations:"),
                self.exclude_widget,
                *self.label_widgets,
            ]
        )
        w_info.layout.padding = "20px"
        self.ui = widgets.Tab(
            children=[
                widgets.VBox(
                    children=[
                        w_header,
                        widgets.HBox(children=[self.w_img, w_info]),
                    ]
                )
            ]
        )
        self.ui.set_title(0, "Annotator")

        # Fill UI with content
        self.update_ui()