Creating the same UI panels in different Blender areas with no code duplication

To create several identical UI panels with the same set of fields and buttons in different areas in Blender, the easiest way is to copy the panel code and replace the parameters that determine in which area the panel will be shown.

The main disadvantage of this method is code duplication, which can make difficulties in the future – when editing panels, changes must be made to each copy of the code, instead of changing it at once for all panels.

The solution to this problem seems to use inheritance – we write a class for one panel, and then we simply inherit the code from this class for all other panels.

However, the Blender API does not allow us to do this directly.

Let’s define a class for a simple panel with the single button that calls the operator for adding a default cube to the scene:

There is no problem with this, we have defined the panel class and registered it for display in the 3D viewport window.

Now let’s try to inherit a class for a new panel, for example, for the Shader Editor area, from it:

Unfortunately, Blender throws an error:

WARN (bpy.rna): bpy_class_call: unable to get Python class for RNA struct ‘TEST_PT_panel_viewport’

and will not be able to correctly display both panels in the required areas.

It seems that inheritance does not solve our problem of code duplication, however, we can still solve it by approaching the definition of panel classes differently.

First, let’s define a generic class without inheriting it from any other classes. Define exactly the same attributes and the same “draw” function in this class, as in the system classes of the UI panels:

This will be our base class, in the “draw” function of which we will describe the entire structure of the UI panel that we need. We will place the creation of all the fields and buttons required on the panel in this function in the future.

Next, let’s define two classes, one for the panel in the 3D viewport area, and the second one for the panel in the Shader Editor area, and inherit them not only from the “bpy.types.Panel” system class but also from our base class “TEST_PT_panel_common” with the panel description.

In these child classes, we have to redefine the parameters responsible for the area to display the panel, so that each of them will be displayed in the desired window.

Only these two classes need to be registered in the Blender Python API. We do not need to register for our base class.

This way, Blender displays both panels in the areas we need correctly and with no errors.

If we need to change something in both panels, we will only need to edit the code in the “draw” function in one place – in our base class.

The final code:

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comment
Inline Feedbacks
View all comments