Cant get value of StringProperty

Been researching this and trying so many things. Multiple days. I figured this should be easy. How do I get the value from a StringProperty?

I took an example from online and am just trying to get the line: print(self.layout.query) to show the result of my StringProperty.

import bpy

class QueryProps(bpy.types.PropertyGroup):

    query= bpy.props.StringProperty(default="testtest")


class SelectByQuery(bpy.types.Operator):

    bl_idname = "object.select_by_query"
    bl_label = "Selection of object by query"

    def execute(self, context):
        print(self.layout.query) ##### I cannot get this to work
        return {'FINISHED'} 
 

class PanelThree(bpy.types.Panel):
    bl_idname = "VIEW3D_PT_SelectionQuery"
    bl_label = "Selection Query"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "querytest"

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

        col = layout.column(align=True)
        rowsub = col.row(align=True)

        rowsub.label(text="SELECT *")

        rowsub = col.row(align=True)
        col2 = layout.column()
        rowsub2 = col2.row()
        rowsub2.operator("object.select_by_query", text="Query")
        rowsub.prop(props, "query", text="")


classes = (
    QueryProps,
    SelectByQuery,
    PanelThree
)


def register():

    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)
    # Register QueryProps
    bpy.types.Scene.QueryProps = bpy.props.PointerProperty(type=QueryProps)


def unregister():

    from bpy.utils import unregister_class
    for cls in classes:
        unregister_class(cls)
    # $ delete QueryProps on unregister
    del(bpy.types.Scene.QueryProps)


if __name__ == "__main__":
    register()

Any helper would be greatly appreciated.

Thanks

import bpy
class QueryProps(bpy.types.PropertyGroup):
    query= bpy.props.StringProperty(default="testtest")

try:
    bpy.utils.unregister_class(QueryProps)
    del bpy.types.Scene.QueryProps
except:
    pass

bpy.utils.register_class(QueryProps)
bpy.types.Scene.QueryProps = bpy.props.PointerProperty(type=QueryProps)

print('property is', bpy.context.scene.QueryProps.query)

bpy.context.scene.QueryProps.query = 'hello'
assert(bpy.context.scene.QueryProps.query == 'hello')

Thank you so much for the reply. I am getting closer but it appears that code I have written disappears when I dont have anything selected. I can show this code to you if you would like to take a look.

Ok found another tutorial out there that did a great job of providing all properties on a Blender Panel.
go down to end here https://blender.stackexchange.com/questions/57306/how-to-create-a-custom-ui

My code is part of an add on that I really dont understand everything 100% but it works. so if anyone is interested you can take a look at it below. There are a lot of things commented out I just wanted something that would work since Ive been at this for several weeks now.

bl_info = {
    "name": "JLE Tools",
    "author": "James Erickson - JLE Studios",
    "version": (3, 0),
    "blender": (2, 79, 0),
    "location": "VIEW3D > Tool Shelf > JleTools",
    "description": "Curve vertex selection, total selection, import and export",
    "category": "Selection and Import"
}

import bpy

from bpy.props import (StringProperty,
                       BoolProperty,
                       IntProperty,
                       FloatProperty,
                       EnumProperty,
                       PointerProperty,
                       )
from bpy.types import (Panel,
                       Operator,
                       PropertyGroup,
                       )


# ------------------------------------------------------------------------
#    Scene Properties
# ------------------------------------------------------------------------

class MySettings(PropertyGroup):

    #my_bool = BoolProperty(
    #    name="Enable or Disable",
    #    description="A bool property",
    #    default = False
    #    )

    #my_int = IntProperty(
    #    name = "Int Value",
    #    description="A integer property",
    #    default = 23,
    #   min = 10,
    #    max = 100
    #    )

    #my_float = FloatProperty(
    #    name = "Float Value",
    #    description = "A float property",
    #    default = 23.7,
    #    min = 0.01,
    #    max = 30.0
    #    )

    my_string = StringProperty(
        name="NewName",
        description=":",
        default="",
        maxlen=1024,
        )

    #my_enum = EnumProperty(
    #    name="Dropdown:",
    #    description="Apply Data to attribute.",
    #    items=[ ('OP1', "Option 1", ""),
    #            ('OP2', "Option 2", ""),
    #            ('OP3', "Option 3", ""),
    #           ]
    #    )
def selectPoints(context, select_type):
    ob = bpy.context.object
    points = ob.data.splines.active.bezier_points
    current_idx = 0

    #need the total points in case the next index is past
    total_points = len(points) - 1

    #find the selected point by using enumerate that allows the array to have a searchable index
    for idx, point in enumerate(points):
            if point.select_control_point:
                    current_idx = idx

    #set the previous and next index
    prev_idx = current_idx - 1
    next_idx = current_idx + 1

    if prev_idx < 0:
            prev_idx = total_points
            
    if next_idx > total_points:
            next_idx = 0
            
    #everything is stored you can now check the parameter
    #and run the selection requested
    if select_type == "next":
        points[current_idx].select_control_point = False
        points[next_idx].select_control_point = True
        
    if select_type == "prev":
        points[current_idx].select_control_point = False
        points[prev_idx].select_control_point = True
        
    if select_type == "all":
        for point in points:
            point.select_control_point = True
        
#end the function for selection
# ------------------------------------------------------------------------
#    Operators
# ------------------------------------------------------------------------

class obj_import_class(bpy.types.Operator):
    bl_idname = "wm.import_obj"
    bl_label = "Import Obj"

    def execute(self, context):
        scene = context.scene
        mytool = scene.my_tool
        md = bpy.context.mode
        if md == 'EDIT_CURVE':
            bpy.ops.object.mode_set(mode='OBJECT')
        if md == "EDIT_MESH":
            bpy.ops.object.mode_set(mode='OBJECT')
        if md == "SCULPT":
            bpy.ops.object.mode_set(mode='OBJECT')
            
        # print the values to the console
        print("Hello World")
        #print("bool state:", mytool.my_bool)
        #print("int value:", mytool.my_int)
        #print("float value:", mytool.my_float)
        print("string value:", mytool.my_string)
        File_loc = 'M:\M_Daz\Blender\!!toBlender33.obj'
        bpy.ops.import_scene.obj(
        filepath=File_loc,
        filter_glob="*.obj;*.mtl",
        use_edges=True,
        use_smooth_groups=True,
        use_split_objects=False,
        use_split_groups=False,
        use_groups_as_vgroups=True,
        use_image_search=True,
        split_mode='OFF',
        axis_forward='-Z',
        axis_up='Y')
    
        #get the current object
        ob = bpy.context.selected_objects[0]
        bpy.ops.object.shade_smooth()
    
        ob.name = mytool.my_string
    
        #print("enum state:", mytool.my_enum)

        return {'FINISHED'}
    
class SelectNextVertexFunction(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "myops.select_next_vertex_function"
    bl_label = "Select Next Curve Vertex"
    
    def execute(self, context):
        selectPoints(context, "next")
        return {'FINISHED'}
        
class SelectPrevVertexFunction(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "myops.select_prev_vertex_function"
    bl_label = "Select Prev Curve Vertex"
    
    def execute(self, context):
        selectPoints(context, "prev")
        return {'FINISHED'}
        
class SelectAllVertexFunction(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "myops.select_all_vertex_function"
    bl_label = "Select All Curve Vertex"
    
    def execute(self, context):
        selectPoints(context, "all")
        return {'FINISHED'}

# ------------------------------------------------------------------------
#    Menus
# ------------------------------------------------------------------------

#class OBJECT_MT_CustomMenu(bpy.types.Menu):
#    bl_idname = "object.custom_menu"
#    bl_label = "Select"
#
#    def draw(self, context):
#        layout = self.layout
#
#        # Built-in example operators
#        layout.operator("object.select_all", text="Select/Deselect All").action = 'TOGGLE'
#        layout.operator("object.select_all", text="Inverse").action = 'INVERT'
#        layout.operator("object.select_random", text="Random")

# ------------------------------------------------------------------------
#    Panel in Object Mode
# ------------------------------------------------------------------------

class OBJECT_PT_CustomPanel(Panel):
    bl_idname = "object.custom_panel"
    bl_label = "Custom Tools"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "TOOLS"    
    bl_category = "JLE_Tools"
    #bl_context = "objectmode"   

    #@classmethod
    #def poll(self,context):
    #    return context.object is not None

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

        #layout.prop(mytool, "my_bool")
        #layout.prop(mytool, "my_enum", text="") 
        #layout.prop(mytool, "my_int")
        #layout.prop(mytool, "my_float")
        layout.prop(mytool, "my_string")
        layout.operator("wm.import_obj")
        #layout.menu(OBJECT_MT_CustomMenu.bl_idname, text="Presets", icon="SCENE")
        layout.separator()
        #Next Vertex Group
        row = layout.row()
        row.label(text="Select Next Vertex", icon='CURVE_DATA')
        row = layout.row()
        row.operator("myops.select_next_vertex_function")
        
                
        #Prev Vertex Group
        row = layout.row()
        row.label(text="Select Prev Vertex", icon='CURVE_DATA')
        row = layout.row()
        row.operator("myops.select_prev_vertex_function")
                
                
        #All Vertex Group
        row = layout.row()
        row.label(text="Select All Vertexes", icon='CURVE_DATA')
        row = layout.row()
        row.operator("myops.select_all_vertex_function")

# ------------------------------------------------------------------------
#    Registration
# ------------------------------------------------------------------------

classes = [SelectNextVertexFunction, SelectPrevVertexFunction, SelectAllVertexFunction, obj_import_class]
def register():
    for cls in classes:
        bpy.utils.register_class(cls)
        
    bpy.utils.register_module(__name__)
    bpy.types.Scene.my_tool = PointerProperty(type=MySettings)
    print("registered")

def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
        
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.my_tool
    print("deleted tool")

if __name__ == "__main__":
    register()

Thanks again to all who helped.

I did some notes on this along with some suggestions.

bl_info = {
    "name": "JLE Tools",
    "author": "James Erickson - JLE Studios",
    "version": (3, 0),
    "blender": (2, 79, 0),
    "location": "VIEW3D > Tool Shelf > JleTools",
    "description": "Curve vertex selection, total selection, import and export",
    "category": "Selection and Import"
}

import bpy
from bpy.props import (StringProperty, BoolProperty, IntProperty, FloatProperty, EnumProperty, PointerProperty)
from bpy.types import (Panel, Operator, PropertyGroup)

# ------------------------------------------------------------------------
#    Scene Properties
# ------------------------------------------------------------------------
class MySettings(PropertyGroup):
    my_path = StringProperty(name="Path", description="Location of .obj file", default="", maxlen=1024)
    my_string = StringProperty(name="Name", description="New name to be given to the imported model", default="", maxlen=1024)
    # OK

def selectPoints(context, select_type):
    ob = bpy.context.object
    points = ob.data.splines.active.bezier_points
    current_idx = 0

    #need the total points in case the next index is past
    total_points = len(points) - 1

    #find the selected point by using enumerate that allows the array to have a searchable index
    for idx, point in enumerate(points):
            if point.select_control_point:
                    current_idx = idx

    #set the previous and next index
    prev_idx = current_idx - 1
    next_idx = current_idx + 1

    if prev_idx < 0:
            prev_idx = total_points
            
    if next_idx > total_points:
            next_idx = 0
            
    #everything is stored you can now check the parameter
    #and run the selection requested
    if select_type == "next":
        points[current_idx].select_control_point = False
        points[next_idx].select_control_point = True
        
    if select_type == "prev":
        points[current_idx].select_control_point = False
        points[prev_idx].select_control_point = True
        
    if select_type == "all":
        for point in points:
            point.select_control_point = True

    # OK
        
# ------------------------------------------------------------------------
#    Operators
# ------------------------------------------------------------------------

class obj_import_class(bpy.types.Operator):
    '''Import the OBJ file from location'''
    bl_idname = "wm.import_obj"
    bl_label = "Import Obj"

    # ----
    # as a way to double check your addon is valid
    # you can do the import only from object mode
    @classmethod
    def poll(self,context):
        return context.mode == 'OBJECT'
    # ----

    def execute(self, context):
        # ----
        # the context mode switch should not be needed since
        # you can only can invoke the operator from OBJECT mode: see: poll()
        # bpy.ops.object.mode_set(mode='OBJECT')
        # OK
        # ----

        # ----
        # deselect all objects first so the imported object then gets selected automatically
        # (otherwise with bpy.context.selected_objects[0] you assume that the first
        # object depends on how it was appended in the list (see: >>> list(bpy.context.scene.objects) )
        bpy.ops.object.select_all(action='DESELECT')
        # ----

        # ----
        # to load OBJ from this PATH (?)
        # make sure it exists first
        import os.path as path
        importpath = context.scene.my_tool.my_path
        if path.exists(importpath) and path.isfile(importpath):
            pass
        else:
            print('could not locate file `%s`' % importpath)
            print('please set a valid path')
            return {'FINISHED'}
        # ----

        # ----
        # import seems OK
        bpy.ops.import_scene.obj(
            filepath=context.scene.my_tool.my_path,
            filter_glob="*.obj", # only obj files (?) # filter_glob="*.obj;*.mtl",
            use_edges=True,
            use_smooth_groups=True,
            use_split_objects=False,
            use_split_groups=False,
            use_groups_as_vgroups=True,
            use_image_search=True,
            split_mode='OFF',
            axis_forward='-Z',
            axis_up='Y')
        # ----
        
        # ----
        # get the current object (since now the imported is the selected) and set the new name
        # (let's add again some precaution in case you don't want to rename the model - just leave it as it is)
        ob = bpy.context.selected_objects[0]
        if len(context.scene.my_tool.my_string) > 0:
            ob.name = context.scene.my_tool.my_string
        print("Loaded OBJ:", ob.name)
        # and change the smoothing
        bpy.ops.object.shade_smooth()
        # ----

        # finish
        return {'FINISHED'}
    
class SelectNextVertexFunction(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "myops.select_next_vertex_function"
    bl_label = "Select Next Curve Vertex"
    def execute(self, context):
        selectPoints(context, "next")
        return {'FINISHED'}
    # OK
        
class SelectPrevVertexFunction(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "myops.select_prev_vertex_function"
    bl_label = "Select Prev Curve Vertex"
    def execute(self, context):
        selectPoints(context, "prev")
        return {'FINISHED'}
    # OK
        
class SelectAllVertexFunction(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "myops.select_all_vertex_function"
    bl_label = "Select All Curve Vertex"
    def execute(self, context):
        selectPoints(context, "all")
        return {'FINISHED'}
    # OK

# ------------------------------------------------------------------------
#    Panel in Object Mode
# ------------------------------------------------------------------------
class OBJECT_PT_CustomPanel(Panel):
    bl_idname = "object.custom_panel"
    bl_label = "Custom Tools"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "TOOLS"    
    bl_category = "JLE_Tools"

    # ----
    # bl_context = "objectmode" # this will show the panel only when mode is `object`
    # but if you want to display it always just do not add the property
    # ie: bpy.context.mode == 'OBJECT'

    # I tested adding this method and has no effect (so it can be removed)
    # @classmethod
    # def poll(self,context):
    #     return context.object == None
    # ----

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

        # ----
        # I assume that this is only needed while in the object mode
        # (same as the menu below for the curves)
        if context.mode == 'OBJECT':
            layout.prop(mytool, "my_path", icon="DISK_DRIVE")
            layout.prop(mytool, "my_string")
            layout.operator("wm.import_obj")
            #layout.menu(OBJECT_MT_CustomMenu.bl_idname, text="Presets", icon="SCENE")
            layout.separator()
        # ----

        # ----
        # A SIDENOTE:
        # since these operations have only meaning while in the edit curve mode
        # is only then that they can be enabled and be useful
        # (eg: when I am in the object mode I can just use anything from this)
        if context.mode == 'EDIT_CURVE':
            #Next Vertex Group
            row = layout.row()
            row.label(text="Select Next Vertex", icon='CURVE_DATA')
            row = layout.row()
            row.operator("myops.select_next_vertex_function")
            
            #Prev Vertex Group
            row = layout.row()
            row.label(text="Select Prev Vertex", icon='CURVE_DATA')
            row = layout.row()
            row.operator("myops.select_prev_vertex_function")
                    
            #All Vertex Group
            row = layout.row()
            row.label(text="Select All Vertexes", icon='CURVE_DATA')
            row = layout.row()
            row.operator("myops.select_all_vertex_function")
        # ----

# ------------------------------------------------------------------------
#    Registration
# ------------------------------------------------------------------------
classes = [SelectNextVertexFunction, SelectPrevVertexFunction, SelectAllVertexFunction, obj_import_class]
def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    bpy.utils.register_module(__name__)
    bpy.types.Scene.my_tool = PointerProperty(type=MySettings)
    print("registered")
    # OK

def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.my_tool
    print("deleted tool")
    # OK

if __name__ == "__main__":
    # this is a trick to forcefully
    # unregister and register the module
    # (guaranteed to remove everything the addon has and start again anew
    # such as 'properties'/'modal handlers'/'persistent events' tend to get
    # stuck and get multiple-registered each time)
    try: unregister()
    except: pass
    register()
    # OK

You are a master arent you? wow thanks so much for doing this I will review and maybe understand better. Thanks

Thank you, though I have tried Blender scripting quite a few times, I got used to it (both it’s quirks and API design). :slight_smile:

Awesome! I have a silly question. I program in many languages (not Python though) I see that in your comments you write #OK a lot is that just a way to imply when the comment is complete? Sorry I was just curious.

This was a pure comment, no significant purpose, more like “OK I checked this block and it was good”.

There can be various special comments depending on third party external tools. But most significant is the “region” where allows you to fold the blocks of code (especially in VSCode).

#region first part
#endregion