Button¶
It’s a class.
Button is the most important complete UI that can be created. Complete , means all other UI types are created using Button only, either by inheritance or by creating it’s instance.
Therefore, TextField, IntField, CheckBox etc are all child of Button or have Button instance. Their Vector counterpart eg. VectorIntField has three Button instances.
Note
This page and Event and Callback are very important, read carefully with patience
Simplest button requires two non-optional parameter:
- op:
type: Boss_OT_base_ui
It’s reference of the operator, inherited from Boss_OT_base_ui
- rectData:
type: RectData
Rectangle of the panel.
1 2 3 4 5 6 7 | from boss.ui_creator import UICreator,RectData #,Button
def ui_elements(op):
# Button(op, RectData(10,10,100,50))
# or
UICreator.button(op,RectData(10,10,100,50))
|
Default behaviour:
By default button is draggable.
By default button can’t be dragged outside the view region.
By default button adds callback to change color
onEnter
andonExit
.
Above code does nothing when clicked, a more usable Button can be created using following code:
from boss.ui_creator import UICreator, Boss_OT_base_ui
def createCube():
import bpy
bpy.ops.mesh.primitive_cube_add(size=2)
def ui_elements(op:Boss_OT_base_ui):
UICreator.button(op, (10, 10, 200, 100), 'Cube', createCube)
Above code Creates a Button near bottom left, when clicked, a Cube is created.
from boss.ui_creator import UICreator
def ui_elements(op):
UICreator.button(op, (10, 60, 100, 50), 'Cube',
lambda : exec('\n'.join(('import bpy',"bpy.ops.mesh.primitive_cube_add(size=2)"))))
Above code does the same but uses lambda function. This way you can create several buttons without explicitly defining function.
Here is how a button will look with all the supported parameters
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 30 31 32 33 34 35 36 37 | from boss.ui_creator import UICreator, Boss_OT_base_ui, ButtonData, RectData
def onClicked():
print('Button is Clicked')
def dragging(some_param):
print(some_param)
def onWheel(caller, addby):
caller.param += addby
print('param is now', caller.param)
def ui_elements(op: Boss_OT_base_ui):
UICreator.button(
op=op,
rectData=RectData(10, 110, 200, 100),
text='ButtonText',
buttonData=ButtonData(
onClick=onClicked,
onMouseEnter=lambda: print('mouse entered'),
onMouseExit=lambda: print('mouse exited'),
onWheelUp=(onWheel, 1),
onWheelDown=(onWheel, -1),
onDragBegin=(dragging, 'dragging is started'),
onDrag=(dragging, "it's being dragged"),
onDragEnd=(dragging, 'dragging is ended')
),
ttt='tool tip text',
tti='',
canDrag=True,
parent=None,
rectIsLocal=False,
param=100
)
|
You can think of Button as, Button = It’s Shape and Size + Interectivity, where Shape and Size is defined by the parameters that are part of creating a Panel and Interactivity is provided using
ButtonData
object.So, Button inherits from Panel, and ButtonData is only extra parameter that is required. You can compare Panel Parameters with above code and see the ButtonData is the extra parameter.
ButtonData¶
It’s a class.
This class object is used to pass callback function for button events.
This is part of the above code, that first creates ButtonData object, then uses this buttonData to create Button.
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | from boss.ui_creator import UICreator, Boss_OT_base_ui, ButtonData, RectData
def createCube():
import bpy
bpy.ops.mesh.primitive_cube_add(size=2)
def onClicked():
print('Button is Clicked')
def dragging(some_param):
print(some_param)
def onWheel(caller, addby):
caller.param += addby
print('param is now', caller.param)
def ui_elements(op: Boss_OT_base_ui):
buttonData = ButtonData(
onClick=onClicked,
onMouseEnter=lambda: print('mouse entered'),
onMouseExit=lambda: print('mouse exited'),
onWheelUp=(onWheel, 1),
onWheelDown=(onWheel, -1),
onDragBegin=(dragging, 'dragging is started'),
onDrag=(dragging, "it's being dragged"),
onDragEnd=(dragging, 'dragging is ended')
)
UICreator.button(
op=op,
rectData=RectData(10, 110, 200, 100),
text='ButtonText 1',
buttonData=buttonData,
ttt='tool tip text',
param=100
)
UICreator.button(
op=op,
rectData=RectData(10, 210, 200, 100),
text='ButtonText 2',
buttonData=buttonData,
ttt='tool tip text',
param=100
)
|
From the above code you can see, Several buttons can be created using same buttonData.
Notes:
You can create buttons in a loop with the same buttonData, in different locations (using different RectData list).
Button doesn’t store reference to buttonData.
Obviously, You don’t need all the callbacks in one Button, this example is just for demonstration, add callback only for what you need.
Note
You must have read event and callbacks by now.
Button Events
onClick : called when button is clicked
onHover : onHover isn’t implemented.
onMouseEnter : when mouse entered the rect of button
onMouseExit : when mouse exited the rect of button
onWheelUp : mouse wheel (middle button) rolled up
onWheelDown : mouse wheel (middle button) rolled down.
onDragBegin : when mouse (LMB) is pressed.
onDrag : when mouse (LMB) move moves, being pressed.
onDragEnd : when mouse (LMB) if lifted
Following code shows all the add_eventName
method of Button object.
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 30 31 32 33 34 | from boss.ui_creator import UICreator, Boss_OT_base_ui, RectData
def onClicked():
print('Button is Clicked')
def dragging(some_param):
print(some_param)
def onWheel(caller, addby):
caller.param += addby
print('param is now', caller.param)
def ui_elements(op: Boss_OT_base_ui):
button = UICreator.button(
op=op,
rectData=RectData(10, 110, 200, 100),
text='ButtonText',
buttonData=None,
ttt='tool tip text',
param=100
)
button.add_onClick(onClicked)
button.add_onMouseEnter(lambda: print('mouse entered'))
button.add_onMouseExit(lambda: print('mouse exited'))
button.add_onWheelUp((onWheel, 1))
button.add_onWheelDown((onWheel, -1))
button.add_onDragBegin((dragging, 'dragging is started'))
button.add_onDrag((dragging, "it's being dragged"))
button.add_onDragEnd((dragging, 'dragging is ended'))
|
Notes:
Every button added needs to be checked whether mouse cursor is within its rect. It happens whenever mouse moves. More buttons you add, more time it would take. Generally, 10 to 20 buttons, are required for creating any simple functionality.But, create 100,200 buttons is still doable. In future updates, as project will grow, there will be some way to accelerate this using trees, hashing, area partitioning etc.
Since Panel isn’t interactive, it has very few uses. During development, a
Panel
was enough to be draggable and change it’s color. To keep all the interactivity and callbacks in one class, all code for callback was removed fromPanel
toButton
. Now a Button is required to changePanel
properties ofcanDrag
and color.What is Click? , If mouse is down and up in the same co-ordinate position, the up event becomes the click. If mouse moved, even by 1 px, when held down, its NOT a click. (its a Drag). Some times click doesn’t work, this could be the reason.