@@ -366,7 +366,7 @@ def _to_dict(lbs, elems):
366366 region = (x , y , w , h )
367367
368368 results = [None ] * len (labels )
369- paths = [self .state . map_images [ la ] for la in labels ]
369+ paths = [self ._search_image_file ( la ) for la in labels ]
370370
371371 if threshold :
372372 # TODO: Figure out how we should do threshold
@@ -400,6 +400,10 @@ def _find_multiple_helper(self, haystack, region, confidence, grayscale, needle)
400400 ele = cv2find .locate_all_opencv (
401401 needle , haystack , region = region , confidence = confidence , grayscale = grayscale
402402 )
403+ try :
404+ ele = next (ele )
405+ except StopIteration :
406+ ele = None
403407 return ele
404408
405409 def find (self , label , x = None , y = None , width = None , height = None , * ,
@@ -492,6 +496,93 @@ def find_until(self, label, x=None, y=None, width=None, height=None, *,
492496 self .state .element = ele
493497 return ele
494498
499+ def find_all (self , label , x = None , y = None , width = None , height = None , * ,
500+ threshold = None , matching = 0.9 , waiting_time = 10000 , grayscale = False ):
501+ """
502+ Find all elements defined by label on screen until a timeout happens.
503+
504+ Args:
505+ label (str): The image identifier
506+ x (int, optional): Search region start position x. Defaults to 0.
507+ y (int, optional): Search region start position y. Defaults to 0.
508+ width (int, optional): Search region width. Defaults to screen width.
509+ height (int, optional): Search region height. Defaults to screen height.
510+ threshold (int, optional): The threshold to be applied when doing grayscale search.
511+ Defaults to None.
512+ matching (float, optional): The matching index ranging from 0 to 1.
513+ Defaults to 0.9.
514+ waiting_time (int, optional): Maximum wait time (ms) to search for a hit.
515+ Defaults to 10000ms (10s).
516+ grayscale (bool, optional): Whether or not to convert to grayscale before searching.
517+ Defaults to False.
518+
519+ Returns:
520+ elements (collections.Iterable[NamedTuple]): A generator with all element coordinates fount.
521+ None if not found.
522+ """
523+ def deduplicate (elems ):
524+ def find_same (item , items ):
525+ x_start = item .left
526+ x_end = item .left + item .width
527+ y_start = item .top
528+ y_end = item .top + item .height
529+ similars = []
530+ for itm in items :
531+ if itm == item :
532+ continue
533+ if (itm .left >= x_start and itm .left <= x_end )\
534+ and (itm .top >= y_start and itm .top <= y_end ):
535+ similars .append (itm )
536+ continue
537+ return similars
538+
539+ index = 0
540+ while True :
541+ try :
542+ dups = find_same (elems [index ], elems [index :])
543+ for d in dups :
544+ elems .remove (d )
545+ index += 1
546+ except IndexError :
547+ break
548+ return elems
549+
550+ self .state .element = None
551+ screen_w , screen_h = self ._dimensions
552+ x = x or 0
553+ y = y or 0
554+ w = width or screen_w
555+ h = height or screen_h
556+
557+ region = (x , y , w , h )
558+
559+ element_path = self ._search_image_file (label )
560+
561+ if threshold :
562+ # TODO: Figure out how we should do threshold
563+ print ('Threshold not yet supported' )
564+
565+ start_time = time .time ()
566+
567+ while True :
568+ elapsed_time = (time .time () - start_time ) * 1000
569+ if elapsed_time > waiting_time :
570+ return None
571+
572+ haystack = self .get_screen_image ()
573+ it = cv2find .locate_all_opencv (element_path , haystack_image = haystack ,
574+ region = region , confidence = matching , grayscale = grayscale )
575+
576+ eles = [ele for ele in it ]
577+ if not eles :
578+ continue
579+ eles = deduplicate (list (eles ))
580+ for ele in eles :
581+ if ele is not None :
582+ self .state .element = ele
583+ yield ele
584+ break
585+
495586 def find_text (self , label , x = None , y = None , width = None , height = None , * , threshold = None , matching = 0.9 ,
496587 waiting_time = 10000 , best = True ):
497588 """
0 commit comments