Difference between revisions of "How to make a button"
(One intermediate revision by the same user not shown) | |||
Line 54: | Line 54: | ||
[[File:ButtonClick.gif]] | [[File:ButtonClick.gif]] | ||
+ | == Using a Sprite and the events module == | ||
+ | |||
+ | The [[events]] module in /sys/lib/events provides a framework for event-driven programming. With this approach, you use a subclass of [[Sprite]] (called <c>EventSprite</c>) which has methods like <c>onMouseOver</c>, <c>onMouseExit</c>, <c>onDrag</c>, and <c>onDragEnd</c>. By implementing the drag events, we can get proper button behavior. The effect looks just like the example above, but requires less code and is a little neater. It also integrates better with any other event-based code that may be running at the same time. | ||
+ | |||
+ | <ms>import "events" | ||
+ | clear | ||
+ | |||
+ | button = new events.EventSprite | ||
+ | button.image = file.loadImage("/sys/pics/Block3.png") | ||
+ | button.x = 350; button.y = 550 | ||
+ | button.onDrag = function | ||
+ | if self.contains(mouse) then | ||
+ | self.tint = color.silver | ||
+ | else | ||
+ | self.tint = color.white | ||
+ | end if | ||
+ | end function | ||
+ | button.onDragEnd = function | ||
+ | if self.tint == color.silver then | ||
+ | self.action | ||
+ | self.tint = color.white | ||
+ | end if | ||
+ | end function | ||
+ | button.action = function | ||
+ | print "Button clicked!" | ||
+ | end function | ||
+ | button.start | ||
+ | |||
+ | events.eventLoop.run</ms> | ||
+ | |||
+ | == Using a DialogButton on the text display == | ||
+ | |||
+ | You can also make a button on the text display, using special characters (<c>char(57856)</c> and <c>char(57857)</c>) to draw the button endcaps. The [[textUtil]] module in /sys/lib/textUtil provides a <c>DialogButton</c> class that provides drawing, hit detection, and mouse-tracking in a convenient way. This is often used along with the <c>Dialog</c> class, but it doesn't have to be; <c>DialogButton</c> can be used on its own, as shown here. | ||
+ | |||
+ | <ms>import "textUtil" | ||
+ | clear | ||
+ | |||
+ | button = new textUtil.DialogButton | ||
+ | button.caption = "Click Me" | ||
+ | button.x = 15; button.y = 22 | ||
+ | button.draw | ||
+ | |||
+ | row = 25 | ||
+ | while true // (press Control-C to exit) | ||
+ | yield | ||
+ | if button.contains(mouse) and button.trackHit then | ||
+ | text.row = row; print "Clicked!" | ||
+ | row -= 1 | ||
+ | end if | ||
+ | end while</ms> | ||
+ | |||
+ | [[File:TextButtonClick.gif]] | ||
[[Category:Mini Micro]] | [[Category:Mini Micro]] | ||
[[Category:How To]] | [[Category:How To]] |
Latest revision as of 14:43, 30 August 2024
There are several ways to make a clickable button in Mini Micro. All methods involve drawing some clickable area on the screen, detecting when that area has been clicked, and then tracking the mouse while the button remains down.
For proper button behavior, the button should change in some way (appear darker or shift/scale) to indicate it is pressed, as long as the button is held down but only while the mouse is within the button bounds. If the mouse is dragged outside the bounds, the button should pop back up, and if released in this state it should not count as a click (this is how a user can "cancel" a button click if they realize they made a mistake before releasing the mouse button).
Using a Sprite and No Import Modules
The core of this technique is described in How to detect a click on a sprite. But in the example code below, we make it a bit more general, adding an isClicked
method to the Sprite class that can perform button behavior for any sprite. Then the main program needs only call isClicked
on each button sprite whenever the mouse button goes down, and handle the button click if this method returns true.
clear
// Prepare the sprite we want to use as a button.
button = new Sprite
button.image = file.loadImage("/sys/pics/Block3.png")
button.x = 350; button.y = 550
display(4).sprites.push button
// Function to check for clicks, with button behavior.
// (Call this when the mouse button is pressed.)
Sprite.isClicked = function
// Ensure the self has a bounds.
if not self.localBounds then
self.localBounds = new Bounds
self.localBounds.width = self.image.width
self.localBounds.height = self.image.height
end if
// Track the mouse until the button is released,
// showing the button as "pressed" whenever the
// mouse is within the self bounds.
while mouse.button
if self.contains(mouse) then
self.tint = color.silver
else
self.tint = color.white
end if
yield
end while
self.tint = color.white
// Return whether the mouse was released within bounds.
return self.contains(mouse)
end function
// Main loop.
while true // (press Control-C to exit)
yield
if mouse.button then
// The mouse button is down. Check each of our buttons,
// and do whatever they should do if clicked.
if button.isClicked then
print "Button clicked!"
end if
end if
end while
Using a Sprite and the events module
The events module in /sys/lib/events provides a framework for event-driven programming. With this approach, you use a subclass of Sprite (called EventSprite
) which has methods like onMouseOver
, onMouseExit
, onDrag
, and onDragEnd
. By implementing the drag events, we can get proper button behavior. The effect looks just like the example above, but requires less code and is a little neater. It also integrates better with any other event-based code that may be running at the same time.
import "events"
clear
button = new events.EventSprite
button.image = file.loadImage("/sys/pics/Block3.png")
button.x = 350; button.y = 550
button.onDrag = function
if self.contains(mouse) then
self.tint = color.silver
else
self.tint = color.white
end if
end function
button.onDragEnd = function
if self.tint == color.silver then
self.action
self.tint = color.white
end if
end function
button.action = function
print "Button clicked!"
end function
button.start
events.eventLoop.run
Using a DialogButton on the text display
You can also make a button on the text display, using special characters (char(57856)
and char(57857)
) to draw the button endcaps. The textUtil module in /sys/lib/textUtil provides a DialogButton
class that provides drawing, hit detection, and mouse-tracking in a convenient way. This is often used along with the Dialog
class, but it doesn't have to be; DialogButton
can be used on its own, as shown here.
import "textUtil"
clear
button = new textUtil.DialogButton
button.caption = "Click Me"
button.x = 15; button.y = 22
button.draw
row = 25
while true // (press Control-C to exit)
yield
if button.contains(mouse) and button.trackHit then
text.row = row; print "Clicked!"
row -= 1
end if
end while