Kodi Community Forum

Full Version: onDoubleClick isn't called
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
In my addons, I make use of onClick() from WindowXMLDialog to determine when certain controls are clicked.
When trying to do the same with onDoubleClick, it's never called. I am using Helix, and this particular function is in the API list:
http://mirrors.xbmc.org/docs/python-docs...mcgui.html

Is there more to it?
What are you doubleclicking on? If an object does not support doubleclicking it will never fire. For example if you try to capture a doubleclick on a button it will never fire. What you could do is add a 1 second timer to the onclick if it is a button and have a boolean that resets if the 1 second expires, otherwise if it is not expired the 2nd click can be captured as a doubleclick using your own logic.
I could try that. But explain why a button doesn't support a doubleclick? The doubeclick is technically coming from WindowXMLDialog. It then should tell you what control you doubleclicked on. This is how onclick works.

The Button control itself does not have an onclick method, the Window does. The Window then reports what control the onClick took place.
According to the docs WindowXMLDialog supports both onClick and onDoubleClick. So, I would assume it should fire.


onClick(...)
onClick(self, int controlId)--onClick method.

This method will receive all click events that the main program will send
to this window.

onDoubleClick(...)
onDoubleClick(self, int controlId)--onClick method.

This method will receive all double click events that the main program will send
to this window.
You would need to ask a one of the Kodi team members. Buttons themselves do Support onclick so I assume it is a built in check. It makes sense, since by design in any application a button is always a user click not a doubleclick. Don't get me wrong obviously I needed a doubleclick for reasons but in general most won't expect a button to be doubleclicked.
Perhaps one will read this thread and give some input. Otherwise, I will implement my own logic, like you recommended. Thanks!
(2016-12-22, 17:27)jgauthier Wrote: [ -> ]Perhaps one will read this thread and give some input. Otherwise, I will implement my own logic, like you recommended. Thanks!

You might want to use less than a second. I think mine was 0.2 before reseting. If time ran out and it resets then it performs click action, if time it has not reset when a user clicks, it resets, ignores click and performs a doubleclick. Not the best implementation bit it worked for my needs.
Can you share your double click logic?
(2016-12-22, 20:54)jgauthier Wrote: [ -> ]Can you share your double click logic?

I can , but it will be tomorrow most likely as I'm out at the office currently.
It is far from the best solution, but it does the trick

PHP Code:
.
           
def onClick(selfcontrolID):
                
from threading import Timer;

               
#add some kind of controlID check

                
if self.clicked:
                    
self.clicked False;
                    
#do doubleclick things here

                
else:

                    
self.clicked True;

                    
Timer(0.15self.doxyz);
                    
t.start();

            
def doxyz(self):
                if 
self.clicked:
                    
self.clicked False;
                    
#do single click things 
(2016-12-23, 05:03)Protocol-X Wrote: [ -> ]It is far from the best solution, but it does the trick

Your code don't work with all controls. The problem is that event onClick interpretate real double click (fast double click) as single click and don't called twice.
You need use onAction method for catching all click events.
For example:

Code:
def __init__(self):
        self.timeout = 1.0 # or 0.5 as you wish
        self.clicker = 0
        self.target_control = 200 # control id

def onAction(self, action):
                
        action_Id = action.getId()
        control_Id = self.getFocusId()
        
        # ACTION_MOUSE_LEFT_CLICK (run self.clicksEvents only if no clicks)
        if action_Id == 100 and self.clicker == 0 and control_Id == self.target_control:
            t = threading.Timer(self.timeout, self.clicksEvents)
            t.start()

        # ACTION_MOUSE_LEFT_CLICK or ACTION_MOUSE_DOUBLE_CLICK  (clicks count +1)
        if action_Id in [103, 100] and control_Id == self.target_control:
            self.clicker += 1
        
        xbmcgui.WindowXMLDialog.onAction(self, action)


    def clicksEvents(self):
        if self.clicker < 2:
            # Single click action
            pass
        else:
            # Multi click action
            pass
        self.clicker = 0
(2016-12-23, 13:30)Taifxx Wrote: [ -> ]
(2016-12-23, 05:03)Protocol-X Wrote: [ -> ]It is far from the best solution, but it does the trick

Your code don't work with all controls. The problem is that event onClick interpretate real double click (fast double click) as single click and don't called twice.
You need use onAction method for catching all click events.
For example:

Code:
def __init__(self):
        self.timeout = 1.0 # or 0.5 as you wish
        self.clicker = 0
        self.target_control = 200 # control id

def onAction(self, action):
                
        action_Id = action.getId()
        control_Id = self.getFocusId()
        
        # ACTION_MOUSE_LEFT_CLICK (run self.clicksEvents only if no clicks)
        if action_Id == 100 and self.clicker == 0 and control_Id == self.target_control:
            t = threading.Timer(self.timeout, self.clicksEvents)
            t.start()

        # ACTION_MOUSE_LEFT_CLICK or ACTION_MOUSE_DOUBLE_CLICK  (clicks count +1)
        if action_Id in [103, 100] and control_Id == self.target_control:
            self.clicker += 1
        
        self.xbmcgui.WindowXMLDialog.onAction(action)


    def clicksEvents(self):
        if self.clicker < 2:
            # Single click action
            pass
        else:
            # Multi click action
            pass
        self.clicker = 0

Much better. Mine was only for testing purposes, but I will use this idea in the future if i need such as task again.

This is what i ended up doing in my final code.

PHP Code:
.
  
def onAction(selfaction):

        
EXIT_CLICK = (
            
xbmcgui.ACTION_MOUSE_DOUBLE_CLICK
            
xbmcgui.ACTION_MOUSE_LONG_CLICK
            
xbmcgui.ACTION_TOUCH_LONGPRESS
        
);


        
actionID action.getId();
        
controlID self.getConrolID(action);

        if 
actionID in EXIT_CLICK and controlID == BACK_BTN:
            
self.close();

            
pass
(2016-12-23, 17:22)Protocol-X Wrote: [ -> ]This is what i ended up doing in my final code.

Don't forget send uncaught events to default method (xbmcgui.WindowXMLDialog.onAction(self, action) or other depending on how you define class) else you will can not close dialog/window by ESC button on keyboard or BACK on remote etc. Wink
(2016-12-23, 17:53)Taifxx Wrote: [ -> ]
(2016-12-23, 17:22)Protocol-X Wrote: [ -> ]This is what i ended up doing in my final code.

Don't forget send uncaught events to default method (xbmcgui.WindowXMLDialog.onAction(self, action) or other depending on how you define class) else you will can not close dialog/window by ESC button on keyboard or BACK on remote etc. Wink

Could you explain? The docs say these are handled by default but I have always had issues without capturing them myself. Or could you show a small example?
Quote:he docs say these are handled by default

Yes it is. But untill than you redefine method ))

Let's create a dialog inherited from class WindowXMLDialog. WindowXMLDialog has default event methods (onClick, onAction, etc.). As default if WindowXMLDialog.onAction method recive 'ESC button was pressed' action dialog must be closed. But if you redefine onAction method in inherited class default WindowXMLDialog.onAction method was not called. Called only onAction from inherited class. If you need catch only click or drag event and you don't want write what class must do if ESC button event was revived you need call default WindowXMLDialog.onAction method (parent method) manually.

Code:
class myDlg(xbmcgui.WindowXMLDialog):

    def onAction(self, action):
        # do something
        # ...

        # call parent method for received action
        xbmcgui.WindowXMLDialog.onAction(self, action)
Ah that was simple. I appreciate the info. This will allow me to remove some additional coding.
Pages: 1 2