How to display an image in the gui?

i want to display an image (not icon) from a selected directory in the gui of my addon.

i don’t want to have this image loaded in blender (in the bpy.data.images collection where you can select these in the UV image-editor)

i also want to update(= change) this image with a function (showing an other image when selecting something in a menu).

i don’t even know if this is possible and how?

Sounds like quite a tall order, especially since you say you don’t want it in bpy.data.images and you do want it in the GUI.

If you want to show an image in the viewport there is a way but bpy.data.images loads the images and you pass opengl the bindcode to draw the texture. And that, AFAIK can only be done in the viewport.

I am eagerly awaiting for someone to prove me wrong.

in a case of an “emergency” i have a plan B.

i would open it into bpy.data.images
when i change the shown image into another one, i would delete the old one.

it would help if i can access the selected value of a prop_search when click to open the selection-window (before i select the next one)
this way i could get the image-name of the previous image and i can remove this from bpy.data.images.

i tried it with a variable containing the image-name (this works, but not when loading an other file with the addon installed)

I tried something kind of similar once. You may need to assume the role of garbage collector to some extent
bpy.types.ID has user_clear and users
make sure there are no other users before you call del.

Also there is this UILayout.template_ID_preview – I haven’t found decent examples for much of the template_*'s … it sounds very intriguingly like exactly what is wanted.

@CodeManX - amazing – thanks.

huh?

You can overlay any space with opengl and draw a texture on top for instance. But as there aren’t custom widgets, nor the required offsets and dimensions (Panel x, y, width, height, visible area), you can’t really integrate it like a native widget.

There’s the preview template widget, which can show a bpy.data.images datablock, but you can’t really control how the image is drawn.

i still have the problem with the image in the ui

at the moment i can select something and this opens an image in the uv editor.

now i want to display this image by name in a side tab of the tool shelf

evertime i select something other, it replaces the old image

how can i do that?

In a context where there’s an ‘image’ context member, you can use context_pointer_set() in layout code to overwrite it (with the reference to the image you want to show). This is basically what allows datablocks to be pinned in the properties editor.

i tried it with

infobox.context_pointer_set(“name”, bpy.data.images[0])

but i don’t see anything.

what have i to add for name and data?

what happens when i want to use an other image (by selecting something in a menu) - does this update the image?

what is infobox?

You are supposed to use an existing context member name, like “scene” and as second parameter the reference to it (bpy.data.scenes[‘foobar’])

infobox is a bpy.types.UILayout.box to create a box

like in http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/3D_interaction/Sun_Position

the preferences box in the first image

and i don’t really know what to fill in there to make this work.

an example how to use this code could help.

I’m actually not sure how to use it right, and I believe it is limited to a very few use cases, where another script or maybe hard layout code picks up the referenced context pointer. To show a preview image, you can just use the direct reference.

import bpy


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout

        row = layout.row()
        # NOTE: works only at 1:1 panel zoom!
        split = row.split(110 / (context.region.width - 45))
        split.template_preview(bpy.data.textures['.hidden'], show_buttons=False)


def register():
    bpy.utils.register_class(HelloWorldPanel)


def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)


if __name__ == "__main__":
    register()


it works very good, but i have a small problem.

it does not update the image in the ui when changing the image of the used texture.

i use this code to assign a image to the texture:

ui_tex.image = img

ui_tex is of a kind of bpy.data.textures.new(“UI_image”, type = “IMAGE”)

and img is an image loaded with bpy.data.images.load.

when i change the image (by selecting something in the ui), i can see the change in the preview of the texture, but not in my ui.

how can i update this?

i tried it again and again, but it does not update the image

i searched for other usages of template_preview in this forum to test it and i found this: bpy.context.active_object.active_material
this shows the selected material

i still have the problem, if i change material color or select an other object with an other material it does not change the preview in my panel.

why does it not update the image (or is this a bug)?

Did you mouse over the interface? The UI only updates when you interact with it.

yes, i did that

edit:

it updates not when i hover with the mouse, but when i resize the panel.

is there a way to update the view manually? (something like a redraw/update function)

Only if you let a modal timer op run in the background tag_redraw() the region all the time.

i tried it with tag_redraw(), also in a modal operator

i used this code to try to update (without modal op)

        for ar in bpy.context.screen.areas:
                if ar.type == "VIEW_3D":
                    for reg in ar.regions:
                        if reg.type == "TOOLS":
                            reg.tag_redraw()

it still does not work

edit:

i tried something and i got something weird
i wrote this small script (based on the blender script templates)

import bpy


class Panel1(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello1"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'


    def draw(self, context):
        layout = self.layout
        
        obj = context.object

        row = layout.row()
        row.label(text="Hello world!", icon='WORLD_DATA')

        row = layout.row()
        row.prop(obj, "name")

        row = layout.row()
        row.template_preview(bpy.context.active_object.active_material, show_buttons=False)
        
        
class Panel2(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello2"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'

    bl_context = "object"

    def draw(self, context):
        layout = self.layout
        
        obj = context.object

        row = layout.row()
        row.label(text="Hello world!", icon='WORLD_DATA')

        row = layout.row()
        row.prop(obj, "name")

        row = layout.row()
        row.template_preview(bpy.context.active_object.active_material, show_buttons=False)


def register():
    bpy.utils.register_class(Panel1)
    bpy.utils.register_class(Panel2)


def unregister():
    bpy.utils.unregister_class(Panel1)
    bpy.utils.unregister_class(Panel2)


if __name__ == "__main__":
    register()


it shows me the material of the selected object in two different places of the blender ui.

the one is under view_3d >> tools and the another one under properties >> window >> object

when i add two objects and give each of them an other material, the preview under properties >> window >> object updates,
but not the preview under view_3d >> tools

what is wrong, is there the code wrong, is this intended or is this a bug in blender (i use the newest version).
(i tried it with my addon to move it to properties >> window > object and that worked, but i want it to have it under view_3d >> tools)

You shouldn’t put it in the view3d tools, it isn’t refreshed 'cause there’s no need to for any default UI elements in there.

BTW: you should give it a bl_category

what do i have to add to bl_category??

and is there a way to solve the update problem except the way to move the addon ui to for example properties >> window >> object.

if not i would move it there to solve the problem quickly