I'm pretty new to Kivy and I'm trying to use the Slider widget. I don't want a function to be executed on_value but rather as soon as the slider is released. How can I implement something like on_release (which exists for Buttons) in the Slider class?
I.e. instead of
Slider:
on_value: root.do_something()
I want to have
Slider:
on_release: root.do_something()
I don't think there's a built in event for this, so you'd need to override on_touch_up. Something like the following should work:
def on_touch_up(self, touch):
released = super(YourSliderSubclass, self).on_touch_up(touch)
if released:
do_something()
return released
This works because its on_touch_up returns True by default if it was actually released, otherwise it returns None.
If you want an event to bind to in kv, you could add your own new event to your slider subclass and dispatch that.
Related
I'm pretty new to Kivy and I'm trying to use the Slider widget. I don't want a function to be executed on_value but rather as soon as the slider is released. How can I implement something like on_release (which exists for Buttons) in the Slider class?
Ou seja, em vez de
Slider:
on_value: root.do_something()
eu quero ter
Slider:
on_release: root.do_something()
The event on_release is provided by the mixin class ButtonBehavior. The class Slider is not inherited from ButtonBehavior, that's why you can't expect that event in Slider. You may also have problem if you want to define a class inheriting from ButtonBehavior and Slider due to the on_touch_up event.
Check more on Kivy documentation.
You can make use of on_touch_up event. You have to pass touch object passed to on_touch_up (args[1]) and slider object (self), then check if event was fired because your slider was grabbed to avoid of firing on_slider_release method from other sources.
Here is and example:
Within your kv file:
Slider:
on_touch_up: root.on_slider_release(args[1], self)
Then on_slider_release implementation:
def on_slider_release(self, touch, widget):
if touch.grab_current == widget:
print('my_slider has been released')
I have a custom MXML component which has a change event declared as:
<mx:Metadata>
[Event(name="change", type="flash.events.Event")]
</mx:Metadata>
The problem is that this event is dispatched whenever I change ANYTHING inside the component including a simple var. There are times when I want to be able to change the value of a var in the component without dispatching a change event. Is there a simple way of disabling the change event and then re-enabling it once I have made the change I want?
I tried to use removeEventListener("change") but it appears I can only do that for a function that has an event listener added. Same for removeEventListener(Event.CHANGE).
Surely there must be a simple way of disabling events declared in
mx:Metadata
yes there are methods on event you can use. So although the event is still dispatched, this gives you complete control of what happens with it.
// first set the useCapture flag to true
// this tell flex that onChange gets the event before it starts bubbling
myCustomComponentThatDispatchesALotOfChangeEvents.addEventListener(Event.CHANGE, onChange, true);
private function onChange(event:Event):void{
// here is the method you want
// this stops the event from bubbling and lets you handle
// all functionality in this listener only
event.stopImmediatePropogation();
// now look at what happened and see if you want to
// do anything else based on what actually changed
}
as a side note, you can also look at Event.preventDefault() which cancel's the events default behavior
"change" is also a flex thing. It you want to only dispatch the event in one particular scenario, make a new event class that SubClasses Event like MyChangeEvent. The when you make your change...
dispatchEvent(new MyChangeEvent(MyChangeEvent.STUFF_CHANGED))
then
myCustomComponentThatDispatchesALotOfChangeEvents.addEventListener(MyChangeEvent.STUFF_CHANGED, onChange);
Can I listen to Alert button click between components using AsyncToken?
Basically, I want to have a method that opens an Alert with buttons and have it return an AsyncToken so that other components calling that method can listen for button click.
Example:
var token:AsyncToken=methodThatOpensAlert();
token.addResponder(new mx.rpc.Responder(buttonClick));
What's the way to do that?
Thank you.
You might be able to use an AsyncToken to achieve this but you could also just register for custom events that you dispatch from the pop up, this is a much cleaner method IMO. Really you've got two relatively clean options I can think of. 1 you make your pop-up dispatch events like "okClicked" "cancelClicked" for different button clicks within the pop-up, you create an instance of the pop up and add listeners then call PopUpManager.addPopUp, or else you do PopUpManager.createPopUp and keep a reference to the returned display object (the instance of the pop-up it created) and add your listeners then. 2 you make two properties in the pop up typed as function, you use them as call backs, so when you create the pop-up you set the okClickedFunction and cancelClickedFunction (or whatever your buttons may be) then in the pop-up you put cilck handlers on the buttons, check to see if the appropriate call-back function is set and call it if so, like
if(okClickedFunction)
okClickedFunction();
Let me know if you have a specific need that makes you think you must use the AsyncToken, but from checking out the docs it looks as though it's strictly meant to work with the other RPC methods and lots of properties are read-only.
EDIT:
[SomeUtilClass.as]
private static function methodThatOpensAlert():CustomAlert
{
return PopUpManager.createPopUp(Application.application, CustomAlert) as CustomAlert;
}
[CustomAlert.as]
[Event(type="flash.events.Event", name="button1Clicked")]
[Event(type="flash.events.Event", name="button2Clicked")]
private function button1Clicked_handler(event:MouseEvent):void
{
dispatchEvent(new Event("button1Clicked", true));
}
private function button2Clicked_handler(event:MouseEvent):void
{
dispatchEvent(new Event("button2Clicked", true));
}
[ThingThatUsesAlert]
var ca:CustomAlert = SomeUtilClass.methodThatOpensAlert();
ca.addEventListener("button1Clicked", button1ClickHandler);
ca.addEventListener("button2Clicked", button2ClickHandler);
And I believe mouse events bubble by default anyhow still so you could really just listen for a click event on the pop up then use the event.target to determine if it was one of the buttons your interested in.
Let me know if you can make sense of this or need more info.
so I am trying to drag around some images in a canvas.
I am adding eventlisteners to the components and calling startDrag() and stopDrag() to pick them up and stuff:
component.addEventListener(MouseEvent.MOUSE_DOWN, component.startDrag)
The problem is that it is selecting the image at its (0,0) location and not where I initially click on it. So there's a sudden "jump" when I click on the image. It is not smooth.
I noticed that startDrag() has two default parameters, one of them is lockCenter and it is default to false. Maybe do I set it equal to true somehow? (I don't know how to pass arguments to my second parameter in addeventlistener)
Another question: if I want to add more conditions to it, like make a new function that uses component.startDrag(), how do I pass the component to this function while adding event listener to it at the same time?
for example: I want to do:
component.addEventListener(MouseEvent.MOUSE_DOWN, some_other_function);
where some_other_function uses component.startDrag();
Thanks!
You should have your event listener call an event handler instead of start drag directly - that way you can pass arguments:
ie:
component.addEventListener(MouseEvent.MOUSE_DOWN, dragStartHandler);
public function dragStartHandler(event:MouseEvent):void{
component.startDrag(true);
}
You don't have to do all that. Use the DragManager. Here's a page to show you how:
http://www.switchonthecode.com/tutorials/simple-flex-drag-and-drop
Flex 3 question:
I trying here to avoid having to bind resources to all my components labels ( ie a button) and find a way to have this automated.
Problem:
It corrupts the layout in design mode to bind directly in the mxml label="{resourceManager.getString('myResources', 'submit')}" and makes the design view useless. but when declaring bindings elsewhere, in actionScript or via a bind tag, it is counter productive and prone to many errors and miss.
Proposition:
I would like to create my own button that automatically invoke resources to localize a button label. So the author puts "Submit" in the mxml description of my button, and when running it would take the value of the label ie "submit" and use resourceManager.getString('myResources', 'submit').
but I can't find the way to override the set label function, Is it possible if yes how? else how can I go about it?
Maybe I am missing an essential process here that would make the use of resources more elegant, as well as how to override such thing as a button's label.
Thanks for your advices.
Create a component called MyButton, extending Button. Then use this:
override public function set label(value:String):void {
super.label = resourceManager.getString('myResources', value) || value;
}
Assuming the resource manager returns "null" or "undefined" this will work, and will only replace the value if it exists in "myResources".
If you don't want to override every component you need to do this with, then you can add a FlexEvent.CREATION_COMPLETE event on every component. Then use a single generic function to do your label localization.