How to create a text Area and parse text within

New to Blender Python programming. I have experience with Actionscript, Javascript, Objective-C for IOS but I have to say Python is really weird.

Anyway, I am having a hard time creating a UI for my script. All I need are two things. A text area I can paste text into, and a button that will parse the text. I can create a button but cannot find any script for creating a text area, or how to reference the text within a text area once it has been created.

Any thoughts?

I’m sorry but I didn’t see or understand any code that showed how to create a GUI TextBox that one can paste text into, and how to retrieve the text in that box as a string variable. Isn’t there any source code out there on how to create a GUI textbox? The GUI commands in Blender Python scripting seem very cryptic to me. For example, buttons are called “operators”, not “buttons”. What are text boxes called?

Coming from “real” programming languages you will be sadly disappointed at the current state of GUI elements as implemented in Blender. Don’t think of them as objects that you can program. They are simply things you can make appear in a panel. There is no text area, just a place where you can type a single line string. Multi-line is currently not supported.

Here is the way I do it. I create a class that encompasses all the variables I need in their various types (int, float, string). Then add that class so it appears as properties for all objects in Blender. Each of the properties can have an event handler associated with it. So you can process specific fields in its own event space. These event handlers are defined in the class itself.

Here is an example that will add an int, float and string to each and every object in Blender. Run the script and select the Object context and scroll to the bottom of the panel. You should see 3 fields. When you change the value of the fields, an event is generated and the value of the field is printed in the Blender console (not python console) which is hidden by default. Unhide the console under the Help menu along the top of the app. Help/Toggle System Console.


import bpy

def updateIntParameter(self,context):
    # This def gets called when one of the properties changes state.
    print(self.my_int)
def updateFloatParameter(self,context):
    # This def gets called when one of the properties changes state.
    print(self.my_float)
def updateStringParameter(self,context):
    # This def gets called when one of the properties changes state.
    print(self.my_string) 
       
class cls_IntFloatString(bpy.types.PropertyGroup):
    # The properties for this class which is referenced as an 'entry' below.
    my_int = bpy.props.IntProperty(name="My Integer", description="Integer.", default=1, min=0, max=12, update=updateIntParameter)    
    my_float = bpy.props.FloatProperty(name="My Float", description="Float.", default=1.0, min=0.000, max=18.0, step=3, precision=4, options={'ANIMATABLE'}, subtype='FACTOR', unit='NONE', update=updateFloatParameter)
    my_string = bpy.props.StringProperty(name="My String", description="Type your string here.", update=updateStringParameter)

bpy.utils.register_class(cls_IntFloatString)

# Add these properties to every object in the entire Blender system (muha-haa!!)
bpy.types.Object.My_List_Index = bpy.props.IntProperty(min= 0,default= 0)
bpy.types.Object.My_List = bpy.props.CollectionProperty(type=cls_IntFloatString)

class IntFloatStringPanel(bpy.types.Panel):
    bl_label = "Int Float String"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"

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

        obj = context.object
        l = len(obj.My_List)
        if l > 0:
            entry = obj.My_List[obj.My_List_Index]
            
            box1 = layout.box() 
            row1 = box1.row()
            row1.label(" Label:", icon='INFO')
            
            # Display properties for each type.
            box1.prop(entry, "my_string", icon='OBJECT_DATAMODE')
            box1.prop(entry, "my_int")
            box1.prop(entry, "my_float")
        else:
            # This list is zero length, so let's add one.
            collection = obj.My_List
            collection.add()


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


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


if __name__ == "__main__":
    register()

In this example you would put your parse code in the def updateStringParameter.

def updateIntParameter(self,context):

This def gets called when one of the properties changes state.

print(self.my_int)

if you do a panel in tool or tool pro panel

is this required for updating or sort of an option ?

when is it required ?

i ahve a big script with many sceen properties
does it also apply to scene proeprties or only object properties/

thanks

IMO the text editor is quite a handy (and multiline) GUI Textbox. Here is a script and sample file. This was cobbled together quickly from the simple operator and simple panel templates available in the good ol text editor.


import bpy


class HelloWorldPanel(bpy.types.Panel):
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"

    
    textblock = None  # text area to use for this panel
    
    
    @classmethod
    def poll(cls,context):
        return bpy.data.texts.get("PASTE TEXT HERE") is not None
    
    
    def draw(self, context):
        layout = self.layout

        obj = context.object
        textbox = bpy.data.texts.get("PASTE TEXT HERE")
        row = layout.row()
        row.label(text="Text Block", icon='WORLD_DATA')
        row = layout.row()
        box = row.box()
        box.prop(textbox,"open_in_info_window",text="OPEN TEXT IN INFO WINDOW")
        for line in textbox.lines:
            row = layout.row()
            row.label(text=line.body)
        
        #use below if in text editor properties
        #row.prop(context.space_data.text,"open_in_info_window")
        row = layout.row()
        row.label(text="Active object is: " + obj.name)
        row = layout.row()
        row.operator("text.simple_operator")

def main(context):
    textblock = HelloWorldPanel.textblock
    for line in textblock.lines:
        line.body = "CHECKED: %s"%line.body
        


class SimpleOperator(bpy.types.Operator):
    '''Tooltip'''
    bl_idname = "text.simple_operator"
    bl_label = "Simple Text Operator"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}

def openInInfoWin(self,context):

    if self.open_in_info_window:
        for area in context.screen.areas:
            if area.type == 'INFO':

                area.type = 'TEXT_EDITOR'
                area.spaces[0].text = HelloWorldPanel.textblock
                break
    else:
        for area in context.screen.areas:
            if area.type == 'TEXT_EDITOR':        
                area.type = 'INFO'
                break
    return None

def register():
    
    bpy.types.Text.open_in_info_window = bpy.props.BoolProperty("Open in INFO window", default=False, update = openInInfoWin)
    textblock  = bpy.data.texts.get("PASTE TEXT HERE")
    if textblock is None:
        textblock  = bpy.data.texts.new("PASTE TEXT HERE")
    
    HelloWorldPanel.textblock = textblock
   
    
    bpy.utils.register_class(HelloWorldPanel)
    bpy.utils.register_class(SimpleOperator)

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

if __name__ in ["__main__","textbox"]:
    register()

PS using the update to toggle the text area into the info window seems to kill blender post using Ctr-z undo, setting it up via an operator is prob the way to go.

Attachments

textbox.blend (80.8 KB)

Thanks batFINGER. That was very helpful. I’m still fumbling around Python, but at least this gives me a starting point.