How to work around an occasional image
My code basically looks like:
wait("image1", FOREVER)
click("image1)
wait("image2", FOREVER)
click("image2")
Sometimes there is an "image1.5" or a known image at a random time.
What is the best way to work through this?
Can you show me an example of how to use an "if", "onAppear", "while exists" etc. or whatever is most appropriate?
Question information
- Language:
- English Edit question
- Status:
- Answered
- For:
- SikuliX Edit question
- Assignee:
- No assignee Edit question
- Last query:
- Last reply:
Revision history for this message
|
#1 |
Try this codes.
def handler1_5(event):
click(
event.
r1 = Region(
r1.highlight(1)
r1.onAppear(
r1.observe(
r1.wait(
r1.click()
r1.wait(
r1.click()
r1.stopObserver()
popup("Click [OK] to finish")
Revision history for this message
|
#2 |
This code clicks an image if finds it and does nothing if image is not present:
======
def try_click(
try:
except FindFailed:
======
Revision history for this message
|
#3 |
@roman, is this possible for multiple images?
Revision history for this message
|
#4 |
[error] script [ PROGRAM.AUTOMATION ] stopped with error in line 1 at column 14
[error] SyntaxError ( 'no viable alternative at input \'"150668957488
def try_click(
try:
except FindFailed:
Revision history for this message
|
#5 |
I am trying to write code at the beginning of the script that says hey:
If image1, image2, or image3 ever show up, take action x,y,z
which will simply be if image1 shows up click image1, if image 2 shows up click image2, etc.
Revision history for this message
|
#6 |
======
def try_click(
try:
except FindFailed:
======
That's wrong.
Correct:
======
# Function definition
def try_click(
try:
except FindFailed:
# function call
try_click(
======
You also may add later:
=====
try_click(image2)
try_click(image3)
=====
Revision history for this message
|
#7 |
def try_click(
try:
except FindFailed:
try_click(
try_click(
try_click(
_______
I put this code before the rest of my script, but now my script won't do anything when I click run.
Again I'm trying to achieve a code where if an image appears it will be clicked, however the image may or may not show at a point in the middle of the script.
Revision history for this message
|
#8 |
Maybe the following approach works:
Split the logic into two parts:
1. the main logic, as already programmed by you
wait("image1", FOREVER)
click("image1")
wait("image2", FOREVER)
click("image2")
and
2. additional logic that runs when that image1.5 shows up
For this you can let an observer run in the background.
def myHandler(e):
print "image 1.5 appeared"
onAppear(
observe(FOREVER, background = True)
(part 2 has to go before part 1)
Revision history for this message
|
#9 |
Instead of print "image1.5 appeared"
Can I use click("image1.5")
I wish to have my program run while I'm away from the computer, right now each time the image pops up I have to manually click it, and then the automation continues
Revision history for this message
|
#10 |
1|def myHandler(e):
2| click(Pattern(
3|onAppear(
4|observe(FOREVER, background = True)
_______
[error] script [ SWFC_LOG_ALL_2+ ] stopped with error in line 4
[error] TypeError ( observe(): takes no keyword arguments )
Revision history for this message
|
#11 |
Sorry, David, you weren't clear with requirements.
Ok, here is a version with infinite loop.
======
# Setting similarity up for my testing purposes, you may or may not use it
Settings.
# Defining function for clicking if image present
def try_click(
try:
except FindFailed:
# Infinite loop, makes looking for images 1, 2 and 3 infinite
while True:
try_
try_
try_
# Code for stopping the script: if it finds image 4 on screen, infinite loop stops
# and does not search for images 1, 2 and 3 anymore
if exists(image4):
break
======
Revision history for this message
|
#12 |
I think you better not use onAppear / observe() for this purpose. They are expected to wait for image until it appears (that is like wait for image1 until it appears, not paying any attention if image2 and image3 are on screen now). Function try_click() does not wait, it just clicks image if it is present now and does nothing if the image is not present.
Revision history for this message
|
#13 |
Settings.
def try_click(
try:
except FindFailed:
while True:
try_
try_
try_
_______
I click run and nothing happens, without the above code my script runs perfectly, aside from the 3 images showing up sometimes
Revision history for this message
|
#14 |
You have to figure where to put it in your script. As I don't see you full code, I can't. If, say, your code should work first and then just "sit and wait and click occasional images", you should put "while True: ..." part in the very end of your script.
"while True: loop" captures the execution flow, and if put before some commands execution never reach that commands.
Revision history for this message
|
#15 |
Yes @Roman, sorry for the lack of code and confusion, and thank you for helping me thus far.
My script consists only of:
Wait(Image_A, FOREVER)
Click(Image_A)
Wait(Image_B, FOREVER)
Click(Image_B)
and continues this way all the way to Image_Z
I want to add a background statement that if image1, image2, or image3 appear they get clicked.
Note: Image1, image2, and image3 may possibly not show up at all, or may possibly show up at some point in between Image_A and Image_Z.
As of right now I watch my script run, and if image 1, 2, or 3 appear I manually click them and then allow my script to continue to run.
So I want to write something that will allow for these images to get clicked if they appear.
What exactly would that code look like?
Revision history for this message
|
#16 |
Hi David,
I have one idea that may be helpful. Please note I am giving you "not tested" code. Also assuming you have main imagesA-Z and sporadic images1-3. The logic will work but wont be very fast
def WaitMainImage(
while True: # endless loop for the main image - return only when main image is found&clicked
if exists(mainImage): click(); return
if exists(image1): click()
if exists(image2): click()
if exists(image3): click()
# here is the list of main images paths
ImagesA_
# MAIN
for img in ImagesA_Z:
WaitMainImage
Revision history for this message
|
#17 |
Hi ndinev,
Yes I do have images A through Z and Images 1, 2 and 3.
=======
def WaitMainImage(
while True:
if exists(mainImage): click(); return
if exists(
if exists(
if exists(
wait(Image_A, FOREVER)
click(Image_A)
wait(Image_B, FOREVER)
etc.
=======
The good news is the script runs and starts waiting for image A and clicks image A, and continues
The bad news is when Image1 and Image2 showed up nothing happened.
So the question is: Why isn't the "if exists(image): click()" working?
Revision history for this message
|
#18 |
ndinev, I'm really only concerned with the occasional unexpected images, not the main images or main sequence.
if ever appear
then click
if doesn't appear
do nothing
Revision history for this message
|
#19 |
when I watched the Youtube tutorials
there is a game automation example
it has a working if exists
but the image is already on the screen, so its just telling the script to reference what's already there
my images are pop ups
they aren't present until they are
Revision history for this message
|
#20 |
You modified ndinev's suggestion in a wrong way.
You just have to take it as it is and insert the image names, and this should work.
Work on this line:
ImagesA_
Revision history for this message
|
#21 |
I actually did that deliberately because (full disclosure)
After Image E is a sign in button
at which point I have my script type text including username and password.
After this sign in process point the wait/click cycle continues.
How can I work in the sign in button using ndinev's suggestion?
How can I use my type text function exactly where I need it to be?
Revision history for this message
|
#22 |
I am going to try to use ndinev's code while making the sign in page an unexpected page (so the sign in image will not be a main image). testing now.
Revision history for this message
|
#23 |
Yea, the specific issue for this scenario is that there will be times where multiple main (expected) images are true.
So having a code sequence of wait/click is necessary, however it still needs to use a background function for unexpected/
Revision history for this message
|
#24 |
click; wait; click; wait; click; wait; click; type; click; click; type; click; click; (unexpected/
This is the main issue I am working with at this time, I'm not trying to overly complicate things, but will get as messy as I need to.
Revision history for this message
|
#25 |
If your primary logic is more complicated that just [:wait - click:], then I would like to go back to my recommendation with an observer.
It seems that there was an error in my first proposal; apparently there is old code in an example of the documentation in http://
Try with something like
def myHandler(e):
onAppear(
observeInBackgr
wait("Image_A.png", FOREVER)
click("
wait("Image_B.png", FOREVER)
click("
wait("Image_C.png", FOREVER)
click("
wait("Image_D.png", FOREVER)
click("
wait("Image_E.png", FOREVER)
click("
type("username")
click(in the password field)
type("password")
wait("Image_F.png", FOREVER)
click("
etc.
Maybe the following approach works:
Split the logic into two parts:
1. the main logic, as already programmed by you
wait("image1", FOREVER)
click("image1")
wait("image2", FOREVER)
click("image2")
and
2. additional logic that runs when that image1.5 shows up
For this you can let an observer run in the background.
(part 2 has to go before part 1)
Revision history for this message
|
#26 |
David,
As far as I understand you have some workflow that have occasional images only at some steps. Why not just at those places use this logic
def WaitMainOrOccas
while True: # endless loop for the main image - return only when main image is found&clicked
if exists(mainImage): click(); return
if exists(
wait(imageA,
wait(imageB,
type("username")
wait(imageC,
type("password")
wait(imageD,
WaitMainOrOccas
wait(imageG,
...
Can you help with this problem?
Provide an answer of your own, or ask DAVID MASTROIANNI for more information if necessary.