According to this question and this example I am trying to add some custom icons to my addon's operators. But I have an "issue".

In both examples, functions draw, register and unregister are in the same file. In my case, register and unregister functions located into my __init__.py file and looks totally different and the draw function located into an other file I have create by the name fu3dm_main.py. Can anyone help me on how I'll apply this example in my case?

Here is how my __init__.py file looks:

bl_info = {
    "name" : "Blah blah blah",
    "author" : "Simonetos The Greek <[email protected]>",
    "description" : "Blah blah blah",
    "blender" : (2, 90, 1),
    "version" : (1, 0, 0),
    "location" : "View3D",
    "warning" : "",
    "category" : "Generic"

import bpy
from . fu3dm      import *
from . fu3dm_main import *

ops = fu3dm.ops

classes = (

register, unregister = bpy.utils.register_classes_factory(classes)

And here is how my fu3dm_main.py file looks:

import bpy
from . fu3dm import *

class fu3dm_main():
    """Main class"""

    class panel(bpy.types.Panel):
        """Main panel class"""

        bl_idname = "fu3dm.main_PT_Panel"
        bl_label = "Blah blah blah"
        bl_space_type = "VIEW_3D"
        bl_region_type = "UI"
        bl_category = "FU3DM"

        def poll(cls, context):
            return bpy.data.collections.get("FU3DM v20.0")

        def draw(self, context):
                layout = self.layout
            #   ┌────────┐
            #   │ Box #1 │
            #   └┬───────┘
                box1 = layout.box()
                box1_col1 = box1.column()

                box1_row1 = box1_col1.split()
            #   ┌┴────┐
            #   │ End │
            #   └─────┘

1 Answer 1


Well I found the solution from this attached file here, and here is a code example...

import os

import bpy
import bpy.utils.previews
from bpy.types import Panel

preview_collections = {}
# If you work with a simple script.
dir = os.path.dirname(bpy.data.filepath)
# If you work with an addon.
# dir = os.path.join(os.path.dirname(__file__), "icons")

pcoll = bpy.utils.previews.new()

for entry in os.scandir(dir):
    if entry.name.endswith(".png"):
        name = os.path.splitext(entry.name)[0]
        pcoll.load(name.upper(), entry.path, "IMAGE")

class VIEW3D_PT_test(Panel):
    bl_label = "TEST"
    bl_category = "TEST"
    bl_space_type = "VIEW_3D"
    bl_region_type = "UI"

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

        layout.prop(scene, "use_gravity", text="Enable Layout")

        col = layout.column()
        col.enabled = scene.use_gravity
        col.operator("object.duplicate_move", text="Custom Icon", icon_value=pcoll["ICON"].icon_id)
        col.operator("object.duplicate_move", text="Built-in Icon", icon="OUTPUT")


Just note, that If you work on an addon, the dir should be like this dir = os.path.join(os.path.dirname(__file__), "icons") and icons should be saved in .png format into folder icons into the same place where your .py file is.

And if you work on a simple script, dir should be like this dir = os.path.dirname(bpy.data.filepath) and icons should be into the same place where your .py and .blend file is.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .