Unfortunately, Blender’s interface does not support word wrapping and multi-line text blocks. Text lines that are too long to be displayed in the panel are cut off. However, multiline text can still be displayed on the panel using several text elements instead of one.
First, let’s create a simple panel in the N-panel of the 3D Viewport window and place a label element with the desired text on it.
Define the panel class and register it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from bpy.types import Panel from bpy.utils import register_class class TEST_PT_private(Panel): bl_idname = 'TEST_PT_test' bl_label = 'MULTILINE TEXT' bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = 'TEST' def draw(self, context): layout = self.layout text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' layout.label(text=text) register_class(TEST_PT_private) |
After executing this code by pressing the “Run Script” button, we will create a new panel “MULTILINE TEXT” on which the text “Loren Ipsum …” will be placed in a single line.
To make the text multi-line, let’s split it into separate lines by spaces according to the panel width.
The width of the current panel in pixels can be obtained from the area context.
1 2 3 |
context.region.width # 438 |
Let’s make a function that will split a text line passed into it so that the length of each line does not exceed the panel width. We can use the “textwrap” module for this.
1 2 3 4 5 6 7 8 |
import textwrap def _label_multiline(context, text, parent): chars = int(context.region.width / 7) # 7 pix on 1 character wrapper = textwrap.TextWrapper(width=chars) text_lines = wrapper.wrap(text=text) for text_line in text_lines: parent.label(text=text_line) |
We pass three parameters to the function:
- context – the window context to get the panel width
- text – text to be shown
- parent – the element on the interface panel on which we will display the text
The “textwrap” module splits text by characters, not by pixels. So we need to count how many characters will fit into a line of the desired length (panel width). Let’s use an average character width of 7 pixels.
1 |
chars = int(context.region.width / 7) # 7 pix on 1 character |
Next, we will get a list of lines into which the text was split.
1 2 |
wrapper = textwrap.TextWrapper(width=chars) text_lines = wrapper.wrap(text=text) |
Next, we create the required number of label elements, each of which contains the next line of text.
1 2 |
for text_line in text_lines: parent.label(text=text_line) |
Having the function let’s replace the text output in our panel with a call to this function. Now all the text is placed on the panel line by line and will even adjust when the panel width changes.
The final code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
from bpy.types import Panel from bpy.utils import register_class import textwrap def _label_multiline(context, text, parent): chars = int(context.region.width / 7) # 7 pix on 1 character wrapper = textwrap.TextWrapper(width=chars) text_lines = wrapper.wrap(text=text) for text_line in text_lines: parent.label(text=text_line) class TEST_PT_private(Panel): bl_idname = 'TEST_PT_test' bl_label = 'MULTILINE TEXT' bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = 'TEST' def draw(self, context): layout = self.layout text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' _label_multiline( context=context, text=text, parent=layout ) register_class(TEST_PT_private) |
You are a genius, thank you so so much, this is AWESOME AND VERY SMART!