wait for image A or wait for image B

Asked by Randy on 2012-04-30

I cant seem to get this to work
it seems to ignore "or RegB.inside().wait(imgB.png,FOREVER)" therefore when imageB appears. When imageB.png appears, imgA.png doesnt seemed to get clicked. Seems like the script only waits for imgA.
Is there an error in my script?

while True:
   RegA.inside().wait(imgA.png,FOREVER) or RegB.inside().wait(imgB.png,FOREVER)
   click(imgA.png)

Question information

Language:
English Edit question
Status:
Solved
For:
Sikuli Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
2012-05-01
Last query:
2012-05-01
Last reply:
2012-05-01

This question was reopened

RaiMan (raimund-hocke) said : #1

--- inside() is no longer necessary with Sikuli X

--- to check wether something might appear and let the script wait for it use exists() instead of wait(), if you want to keeps the script running.

while True:
   RegA.exists(imgA.png,FOREVER) or RegB.exists(imgB.png,FOREVER)
   click(imgA.png)

But this will never work either as you might expect:
- expressions like something or something_else are evaluated from left to right. So first Sikuli waits for imgA. If this never comes, the script will wait forever.
- if imgA comes to existence, the or condition is satisfied and the second expression (wait for imgB) is not evaluated at all.
- so click(imgA) will only be processed, if imgA comes up.

You need the searches be done in parallel and the first one that succeeds lets the script continue:

This is the feature observe() run in background.

def handler(e):
    global isImgA_or_ImgB
    isImgA_or_ImgB = True

RegA.onAppear(imgA, handler)
RegB.onAppear(imgB, handler)
isImgA_or_ImgB = True

while True:
    RegA.observe(FOREVER, background=True)
    RegB.observe(FOREVER, background=True)
    while not isImgA_or_ImgB:
        wait(1)
    RegA.stopObserver()
    RegB.stopObserver()
    click(imgA)

Randy (rchok2) said : #2

Thanks RaiMan, that solved my question.

RaiMan (raimund-hocke) said : #3

Uuups copy&paste error and a logical flaw, so once again:

def handler(e):
    global isImgA_or_ImgB
    isImgA_or_ImgB = True

RegA.onAppear(imgA, handler)
RegB.onAppear(imgB, handler)

while True:
    RegA.observe(FOREVER, background=True)
    RegB.observe(FOREVER, background=True)
    isImgA_or_ImgB = False
    while not isImgA_or_ImgB:
        wait(1)
    RegA.stopObserver()
    RegB.stopObserver()
    click(imgA)

Randy (rchok2) said : #4

Thanks that works now but i dont seem to understand this part can u explain?

    isImgA_or_ImgB = False
    while not isImgA_or_ImgB:
        wait(1)

I'm still experimenting on the use of Observe. After trying the script below nothing happened, did i miss something?

def handler(event):
    click(A )

def handler2(event):
    click(B )

 Thanks
onAppear(C , handler)
onAppear(D, handler2)
observe()

Randy (rchok2) said : #5

def handler(event):
    click(A )

def handler2(event):
    click(B )

onAppear(C , handler)
onAppear(D, handler2)
observe()

* Thanks

Best RaiMan (raimund-hocke) said : #6

--- observe()
... only observes for 3 seconds (the standard waiting tim).
If you want a longer observation, use
observe(some_time)
... where some_time is a value in seconds

During this kind of observe(), the script pauses (max for the given time, if nothing appears).
But it also consumes the given time, if you do not stop the observation in case something appears.

With this form (observe pauses script) you have to do this in the handler:

e.g.
def handler(event):
    event.region.stopObserver()
    click(A )

--- your other question
Thanks that works now but i dont seem to understand this part can u explain?
    isImgA_or_ImgB = False
    while not isImgA_or_ImgB:
        wait(1)

Since in my example I used the form of observe() that runs in parallel in the background, the script continues. In this case I have to set up some actions in the script to not let it end (in a normal workflow you will have a natural waiting point some where in the ongoing script: e.g. wait for the next GUI element).

So here I have a loop, that simply checks every second, wether one of the handlers was fired (using the global variable isImgA_or_ImgB).

And stopping the observing is done in the main workflow, since when running the observation in the background, usually the main workflow "knows" that the observation is no longer needed.

Randy (rchok2) said : #7

Thanks RaiMan, that solved my question.

denywinarto (deny-winarto) said : #8

Hello, i'm also working on a similar script,
the difference is that there would be 3 different images and 3 different actions (instead of just one) respective to the image, e.g :
imgA appears, click a
imgB appears, click b
imgC appears, click c

how do i accomplish this?
thanks