prompt-toolkit / prompt-toolkit/python-prompt-toolkit

Displaying images in dialog boxes?

Open
#1,670 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
10.6k
Forks
815
PR merge metrics
No merged PRs in 30d

Description

Is it possible to display images in a dialog box? Up till now, I have tried the following.

  1. In layout.controls, added the following class ImageControl
class ImageControl(UIControl):

    def __init__(
            self,
            image,
            focusable: FilterOrBool = False,
            modal: bool = False,
            get_cursor_position: Optional[Callable[[], Optional[Point]]] = None,
    ) -> None:
        self.image = image

    def create_content(self, width: int, height: int) -> UIContent:
        
       # get first row of the 1536x1536 image and make it the first element of the list, then the second row and so on.
       # output of below line of code looks like this [[[154 250 102...]]  ,  [[107 144 12 ...]] ,   [[...]], ......]
       # first element is a nested numpy array [[154 250 102...]]. Numbers inside are of type numpy.uint8.

        fragment_image = [self.image[ind:ind + 1] for ind in
                          range(self.image.shape[0])]  



        # removing one level of nested array here
        # output of below code looks like this [[154 250 102...]  ,  [107 144 12 ...] ,   [...], ......]
        # [154 250 102...] is a list, not a numpy array. Elements are of type int
        input_list = []

        change = lambda x: int(x)

        for element in fragment_image:
            to_append = element[0].tolist()
            # for num in to_append:
            # change(num)
            input_list.append(to_append)

        display = lambda i: plt.imshow(i)

        def get_line(i: int):
            return display(input_list[i])

        return UIContent(
            get_line=get_line, line_count=1536  # self.image.shape[0]
        ) 

    def is_focusable(self) -> bool:
        return False
  1. In widgets.base, added a new class image. Modified widgets.base.Label with the above defined class
class Image:

    def __init__(
            self,
            image,
            style: str = "",
            width: AnyDimension = None,
            dont_extend_height: bool = False,
            dont_extend_width: bool = False,
            align: Union[WindowAlign, Callable[[], WindowAlign]] = WindowAlign.LEFT,
            # There is no cursor navigation in a label, so it makes sense to always
            # wrap lines by default.
            wrap_lines: FilterOrBool = True,
    ) -> None:

        self.image = image

        def get_width() -> AnyDimension:
            if width is None:
                text_fragments = to_formatted_text(self.text)
                text = fragment_list_to_text(text_fragments)
                if text:
                    longest_line = max(get_cwidth(line) for line in text.splitlines())
                else:
                    return D(preferred=0)
                return D(preferred=longest_line)
            else:
                return width
       
        self.image_control = ImageControl(self.image) 

        self.window = Window(
            content=self.image_control,
            # width=get_width,
            width=D(min=1),
            height=D(min=1),
            style="class:label " + style,
            dont_extend_height=dont_extend_height,
            dont_extend_width=dont_extend_width,
            align=align,
            wrap_lines=wrap_lines,
        )

    def __pt_container__(self) -> Container:
        return self.window
  1. Made dialog to display an image (the dialog is built upon widgets.dialogs.Label). It works when < body=Label(text="input text here") > is used
class MsgDialog:
    def __init__(self, title, text):
        self.future = Future()

        def set_done():
            self.future.set_result(None)

        ok_button = Button(text="OK", handler=(lambda: set_done()))

        self.dialog = My_Dialog(
            title=title,

            #body=Label(text=text), # Works if we use this line for text instead of the below line
            body=Image(image=input_image),
            buttons=[ok_button],
            width=D(preferred=50),
            height = D(preferred=20),
            modal=True,
        )

    def __pt_container__(self):
        return self.dialog

But it is not working.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading layout.controls, widgets.base, and widgets.dialogs.Label, then reproduce the dialog using body=Image rather than Label. The issue provides no named test or entry point; done should be a clearly defined, supported way for a dialog body to display the supplied image in the terminal UI.

Written by the indexing model from the issue text.

Assessment

Tech stack
matplotlib, numpy, python
Domain
cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.