[1.1.4 PyJnius] Fix 'App NullPointer, MinSimilarity, MoveMouseDelay, Highlight'

Asked by Dirk Schiller on 2019-02-10

sikulix.py
=======

import os, sys

# https://github.com/blackrosezy/gui-inspect-tool
# https://raiman.github.io/SikuliX1/downloads.html
# http://doc.sikuli.org/javadoc/index.html
# https://sikulix-2014.readthedocs.io/en/latest/genindex.html

# Windows 10 Screen Scale > 100% : [error] RobotDesktop: checkMousePosition: should be L[2880,540]@S(1)...
# https://github.com/RaiMan/SikuliX-2014/issues/292
# Solution: Scale back to 100% and remake all Screenshots if not done with 100% Scale

# Found a Solution for the '# pat.similar(1.0) # Throw an Error: TypeError: 'float' object is not callable':

# In 'C:\Users\DOP\AppData\Local\Programs\Python\Python37\Lib\site-packages\jnius\reflect.py' change ( Line 188 with pyjnius Version 1.2.0 ):

# if name != 'getClass' and bean_getter(name) and len(method.getParameterTypes()) == 0:
# lowername = lower_name(name[2 if name.startswith('is') else 3:])
# classDict[lowername] = (lambda n: property(lambda self: getattr(self, n)()))(name)
# continue

# to:

# if name != 'getClass' and bean_getter(name) and len(method.getParameterTypes()) == 0:
# lowername = lower_name(name[2 if name.startswith('is') else 3:])
# if lowername not in methods_name:
# classDict[lowername] = (lambda n: property(lambda self: getattr(self, n)()))(name)
# continue

jarpath = ';' + os.path.dirname(os.path.realpath(__file__)) + '/sikulixapi.jar'
if not 'CLASSPATH' in os.environ:
    os.environ['CLASSPATH'] = jarpath
else:
    os.environ['CLASSPATH'] += jarpath

from jnius import autoclass

App = autoclass('org.sikuli.script.App')

class Sikuli:

    def __init__(self):
        self.mouse = Mouse()
        self.mouse.setMouseMovedAction(0) # 0 - Disable User Mouse Interaction
        Settings.MoveMouseDelay = 0.1 # Doesn't work if Settings.setShowActions(False) is executed afterwards
        Settings.Highlight = False # True - Fires two Times per Action
        # Settings.setShowActions(False) # False - does disable the Settings.MoveMouseDelay Setting
        # Mouse.setMouseMovedHighlight(True) # Doesn't show any Effect
        Settings.MinSimilarity = 0.95
        Settings.DebugLogs = False
        self.screen = Screen()
        self.highlight = True
        self.mouse_move_away_method = 'Offset' # Origin, Offset

    def app(self, app):
        try:
            self.app = App(app)
        except:
            pass
        finally:
            self.app = App(app)

    def get_app(self):
        return self.app

    def app_is_running(self):
        return self.app.isRunning()

    def app_open(self):
        self.app.open()

    def app_close(self):
        self.app.close()

    def move_offset(self, x, y):
        Mouse().move(x, y)

    def move(self, x, y):
        loc = Location(x, y)
        Mouse.move(loc)

    def click_image(self, image, timeout=5):
        if self.mouse_move_away_method == 'Origin':
            self.move(0, 0)
        if self.mouse_move_away_method == 'Offset':
            self.move_offset(-50, -50)
        reg = self.screen.wait(Pattern(image).similar(Settings.MinSimilarity), timeout)
        if self.highlight:
            reg.highlight(1.0) # Float Values lower than 1.0 not possible; reg.highlight() disable the Click Action; Clicks doesn't come trough; Use reg.highlight(<int>) instead
        self.screen.click(image)

robot = autoclass('org.sikuli.script.RobotDesktop')()
mouse = autoclass('org.sikuli.script.Mouse')
location = autoclass('org.sikuli.script.Location')

class Settings(object):
    MoveMouseDelay = 0.5

class RegionMixin(object):

    def __init__(self):
        self._wrapper = None

    def __getattr__(self, item):
        return getattr(self._wrapper, item)

    def __move(self, target=None):
        if target:
            robot.smoothMove(mouse.at(), self.find(target).getTarget(), Settings.MoveMouseDelay * 1000)
        else:
            robot.smoothMove(mouse.at(), self.getTarget(), Settings.MoveMouseDelay * 1000)

    def click(self, target=None):
        self.__move(target)
        if target:
            self._wrapper.click(self.getLastMatch().getTarget())
        else:
            self._wrapper.click()
        return self

    def hover(self, target=None):
        self.__move(target)
        return self

    def sleep(self, secs):
        time.sleep(secs)
        return self

    def doubleClick(self, target=None):
        self.__move(target)
        if target:
            self._wrapper.doubleClick(self.getLastMatch().getTarget())
        else:
            self._wrapper.doubleClick()
        return self

    def rightClick(self, target=None):
        self.__move(target)
        if target:
            self._wrapper.rightClick(self.getLastMatch().getTarget())
        else:
            self._wrapper.rightClick()
        return self

    def getTarget(self):
        return self._wrapper.getTarget()

    def dragDrop(self, from_, to_):
        self._wrapper.dragDrop(from_, to_)
        return self

    def exists(self, target, timeout=1.0):
        if not self._wrapper.exists(target, timeout):
            return False
        else:
            return True

    def wait(self, target, timeout=1.0):
        try:
            obj = self._wrapper.wait(target, timeout)
        except Exception as e:
            return False
        else:
            return obj

    def waitVanish(self, target, timeout=5.0):
        return self._wrapper.waitVanish(target, timeout)

    def getLastMatch(self):
        return Match(self._wrapper.getLastMatch())

    def find(self, target):
        return Match(self._wrapper.find(target))

    def findAll(self, target):
        _iter = self._wrapper.findAll(target)
        while _iter.hasNext():
            yield Match(_iter.next())

    def highlight(self, secs=1.0):
        self._wrapper.highlight(secs)
        return self

    def type(self, astr):
        self._wrapper.type(astr)
        return self

    def paste(self, astr):
        self._wrapper.paste(astr)
        return self

    def pressKey(self, key):
        self._wrapper.keyDown(key)
        self._wrapper.keyUp(key)
        return self

    def above(self, height=None):
        if height:
            return Region(self._wrapper.above(height))
        else:
            return Region(self._wrapper.above())

    def below(self, height=None):
        if height:
            return Region(self._wrapper.below(height))
        else:
            return Region(self._wrapper.below())

    def left(self, height=None):
        if height:
            return Region(self._wrapper.left(height))
        else:
            return Region(self._wrapper.left())

    def right(self, height=None):
        if height:
            return Region(self._wrapper.right(height))
        else:
            return Region(self._wrapper.right())

class Region(RegionMixin):
    def __init__(self, *args):
        super(Region, self).__init__()
        self._wrapper = autoclass('org.sikuli.script.Region')(*args)

class Screen(RegionMixin):
    def __init__(self):
        super(Screen, self).__init__()
        self._wrapper = autoclass('org.sikuli.script.Screen')()

class Match(RegionMixin):
    def __init__(self, match_obj):
        super(Match, self).__init__()
        self._wrapper = match_obj

class Pattern(object):
    def __init__(self, target):
        self._pattern = autoclass('org.sikuli.script.Pattern')(target)

    def __getattr__(self, item):
        return getattr(self._pattern, item)

    def similar(self, sim=0.7):
        return self._pattern.similar(sim)

class Mouse(object):
    def __init__(self):
        super(Mouse, self).__init__()
        self._mouse = autoclass('org.sikuli.script.Mouse')

    def setMouseMovedAction(self, action):
        self._mouse.setMouseMovedAction(action)

    def move(self, location):
        robot.smoothMove(mouse.at(), location, Settings.MoveMouseDelay * 1000)

    def move(self, x, y):
        loc = location(mouse.at().x + x, mouse.at().y + y)
        robot.smoothMove(mouse.at(), loc, Settings.MoveMouseDelay * 1000)

class Key(object):
    BackSpace = 8
    Enter = 13

test/example.py
=============

import sys
sys.path.append('..')
from sikulix import *

sik = Sikuli()
sik.app(r'C:\Apps\Testapp.exe')
sik.app_open()
sik.click_image(r'..\Images\next.png')
sik.click_image(r'..\Images\eula.png')
sik.click_image(r'..\Images\next.png')
sik.click_image(r'..\Images\next.png')
sik.click_image(r'..\Images\install.png')
sik.click_image(r'..\Images\checkbox_launch.png', 360)
sik.click_image(r'..\Images\finish.png')

Question information

Language:
English Edit question
Status:
Solved
For:
Sikuli Edit question
Assignee:
No assignee Edit question
Last query:
2019-02-10
Last reply:
2019-02-10
RaiMan (raimund-hocke) said : #1

Thanks.
Interesting ;-)