Main concept is that Operators executing something based on given data (e.g. convert all polygons of object xy to triangles). Properties on the other hand can either store the actual 'state' of something (e.g. Wireframe ON/OFF) or any 'value' (e.g. Subdivisions=3 or Crease=0.0001).
In fact, Operators like OPS.object.delete() can be called because these are 'functions' (note the parentheses at the end). However, a Property like Object.wireframe just stores True or False so it can not be called (it's basically not a 'function').
Means that you have to write an Operator if you want to change/toggle any Property.
Another way which you might not think of, is expanding each property to make it look like a 'Button', which also gives instant feedback to the user whether the property is ON/OFF.

import bpy
from bpy.types import (Panel, Operator)
# ------------------------------------------------------------------------
# Operators
# ------------------------------------------------------------------------
class SimpleOperator(Operator):
"""Print object name in Console"""
bl_idname = "object.simple_operator"
bl_label = "Simple Object Operator"
def execute(self, context):
print (context.object)
return {'FINISHED'}
# ------------------------------------------------------------------------
# Panel in Object Mode
# ------------------------------------------------------------------------
class OBJECT_PT_CustomPanel(Panel):
bl_idname = "object.custom_panel"
bl_label = "My Panel"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_category = "Tools"
bl_context = "objectmode"
@classmethod
def poll(self,context):
return context.object is not None
def draw(self, context):
layout = self.layout
obj = context.object
layout.label(text="Properties:")
col = layout.column(align=True)
row = col.row(align=True)
row.prop(obj, "show_name", toggle=True, icon="FILE_FONT")
row.prop(obj, "show_wire", toggle=True, text="Wireframe", icon="SHADING_WIRE")
col.prop(obj, "show_all_edges", toggle=True, text="Show all Edges", icon="MOD_EDGESPLIT")
layout.separator()
layout.label(text="Operators:")
col = layout.column(align=True)
col.operator(SimpleOperator.bl_idname, text="Execute Something", icon="CONSOLE")
col.operator(SimpleOperator.bl_idname, text="Execute Something Else", icon="CONSOLE")
layout.separator()
# ------------------------------------------------------------------------
# Registration
# ------------------------------------------------------------------------
def register():
bpy.utils.register_class(OBJECT_PT_CustomPanel)
bpy.utils.register_class(SimpleOperator)
def unregister():
bpy.utils.unregister_class(OBJECT_PT_CustomPanel)
bpy.utils.unregister_class(SimpleOperator)
if __name__ == "__main__":
register()
You should definitely read: How to create a custom UI?