Python and Sikuli - Selecting from a list (multiple) - python

Asking around a different way of doing this.
I am trying to look at the screen, decide if an image exists (from a list) and choose any that are there, then click "go". If none of the list items are there, it would execute click("go.png") and carry on. If there are any list items there, it clicks it and then executes the click("go.png")
wait("start.png", 10)
click("start.png")
class gameOne():
def pickone():
imageFile = ["one.png", "two.png", "three.png"]
if exists(imageFile):
click(imageFile)
click("go.png")
With this, the click("start.png") and click("go.png") work. It seems to just skips the class. No error is given.

You aren't using the class correctly, I'm not sure how you are expecting this to work, but you don't need that for what you're doing:
wait("start.png", 10)
click("start.png")
imageFile = ["one.png", "two.png", "three.png"]
if exists(imageFile):
click(imageFile)
click("go.png")
This should work as intended.

Related

Python QT dropdown list signal changes too often and not once

I have Python 3.9 with PyQt5 5.15.4.
In QT designer, I created a drop down list. In the initialization code, I filled it with the following values:
self.MEMSDropDown.addItems(["Select MEMS" ])
MEMS_avail = ['MEMS_1' , 'MEMS_2' , 'MEMS_3' , 'MEMS_4' , 'MEMS_5' , 'MEMS_6' ]
self.MEMSDropDown.addItems(MEMS_avail)
Then, I do the Signals / Callback connection:
self.MEMSDropDown.currentIndexChanged.connect(self.Changed__MEMSDropDown)
Then, in the function "Changed__MEMSDropDown", I have written:
#self.blockSignals(True)
def Changed__MEMSDropDown(self, i):
self.MEMSDropDown.clear()
print("'Changed__MEMSDropDown' function is called now.")
#self.blockSignals(False)
My problem is now, this function is called TWICE, or, if instead I use "clear" I add more items to the dropdown list, this is seems to be called iteratively again, e.g. 7 times, if I add with the function "self.MEMSDropDown.addItems(MEMS_avail)".
BUT: I want that it is changed only ONCE when I select another item with the mouse. I do not want that this function is called when I add or remove items programatically. I have tried over "block signals", as commented-out now above, but if I comment them in, the program just crashes.
So the program should behave: As soon as the "Changed__MEMSDropDown" is called, it should remove the entry "Select MEMS" from the item list and keep the rest.
What can I do, that the function is called only once, and not multiple times?
Thanks a lot!
See above. P.S.: I am completely new to Python and to QT.
I solved it: It works with: "self.MEMSDropDown.blockSignals(True)" and False.

return Point(int(firstArg), int(secondArg)) # firstArg and secondArg are just x and y number values

I am trying to have pyautogui move the mouse whenever it detects a color but for some reason whenever I try running it keeps on prompting this error, I have run this code before and it worked perfectly fine. pls help
Code
Output
You are getting that error because "locateAllOnScreen" returns a "generator" which can be looped through which contains all instances of the image. You may be looking for "locateOnScreen".
Here are some example on how to use the two different functions:
# Will loop through all instances of 'img.png'
for pos in pyautogui.locateAllOnScreen('img.png')
# Code here...
# Will find one instance and return the position
pyautogui.locateOnScreen('img.png')
This link has some good information on the different methods

Easiest way for sorting a QTreeView

I'm trying to do some basic Qt file manager app in Python 3.6 with PySide2. Code is like this:
class MainWidget(QWidget):
startDir = "."
def __init__(self):
super().__init__()
isDirselectDone = self.selectContentDir()
if isDirselectDone:
self.model = QFileSystemModel()
self.model.setRootPath(self.startDir)
self.tree = QTreeView()
self.tree.setModel(self.model)
self.tree.setSortingEnabled(True)
self.tree.show()
def selectContentDir(self):
print("Selecing game content folder")
self.startDir = QFileDialog.getExistingDirectory()
if(len(self.startDir) == 0):
print("Game content folder loading cancelled")
return False
print("Trying to load ", self.startDir)
return True
My problem is that no matter what is the contents of the chosen directory, the view does not sort the files. I can click oh the headers, and the little arrows are changing, but everything remains in the order it was loaded.
I tried to look for solutions, but the answers either say that you just have to call the setSortingEnabled() and everything magically works (which is not the case), or they describe some voodoo magic rituals involving inheriting from QAbstractTreeSuperAncientGodItemViewDelegate, then re-implement half of the Qt library and finally creating a Tartarus-like maze by connecting slots and signals all over the place.
So what is the easiest / simplest way to make this sorting work according to latest Qt standards?
I found a solution for my case, based on the following assumptions:
These three lines:
model.setRootPath(directory)
tree.setRootIndex(self.model.index(directory))
tree.setSortingEnabled(True)
Seem they have to be in this specific order, and of course the model rootpath and the tree root index has to point to the same directory (during debugging I tried to set them to different ones, just to see what happens when the tree shows just a subset of the model data, but as expected it broke multiple things in the app).
Also, any custom lines (like handling your custom columns) has to happen between the root index setting, and the sorting enable. I don't know if this is really a general rule, it seems kind of arbitrary, but in my project it turned out to be crucial to call setSortingEnabled() as a last step, to make it work.
If your custom columns do not contain simple text (or anything not easily sortable, in my case a combobox) or they are hidden, you'd better exclude that column from the sorting. This is not mandatory, but for me it resulted in faster response time for the other columns.

Cursor Grabbing while using drag_and_drop_by_offset (Python/Selenium)

I need to drag this scale and when I run this code:
HandScale = browser.find_element_by_xpath('//*[#data-xform="scale"]')
GridLineX = browser.find_element_by_class_name('outlined')
bottomLeft = browser.find_element_by_class_name('bottomLeft')
print GridLineX.size
action_chains = ActionChains(browser)
action_chains.drag_and_drop_by_offset(HandScale, 30, 30).click_and_hold(HandScale).perform()
It still has the grabbing effect Shown here:
Is there anyway to remove this effect before running the other part of my script?
I think you just need the release() function in action_chains which is designed to do exactly that. The line to add at the end of your current file would be:
action_chains.release().perform()
Edit after feedback that this didn't work: what if you do the release() inside your existing action_chains, and simply add a pause() after your click_and_hold(HandScale) so that the click is actually held and not immediately released. Finally, since you use a webelement argument in click_and_hold(HandScale) I would try to release on that element with release(HandScale). So, your action_chains might do what you want if you use the following:
action_chains.drag_and_drop_by_offset(HandScale, 30, 30).click_and_hold(HandScale).pause(5).release(HandScale).perform()
If THAT doesn't work, the WebDriver API has a method called reset_actions() that, according to the documentation "Clears actions that are already stored locally and on the remote end". I would add this under your current action_chains, but you could try inserting it before perform() in your current code. The line to add would just look like this:
action_chains.reset_actions().perform()
If none of this works for you, you could try
driver.execute_script("arguments[0].removeAttribute('cursor')", element")
If you need I think can help you figure out what to execute if none of the above works.

function for switching frames in python, selenium

I'm looking for a function that makes it easier to switch between two frames. Right now, every time I need to switch between frames, I'm doing this by the following code:
driver.switch_to.frame(driver.find_element_by_css_selector("frame[name='nav']"))
driver.switch_to.frame(driver.find_element_by_css_selector("frame[name='content']"))
My goal is to get a function that takes an argument just to change nav or content since the rest is basically the same.
What I've already tried is:
def frame_switch(content_or_nav):
x = str(frame[name=str(content_or_nav)] #"frame[name='content_or_nav']"
driver.switch_to.frame(driver.find_element_by_css_selector(x))
But it gives me an error
x = str(frame[name=str(content_or_nav)]
^
SyntaxError: invalid syntax
The way this is written, it's trying to parse CSS code as Python code. You don't want that.
This function is suitable:
def frame_switch(css_selector):
driver.switch_to.frame(driver.find_element_by_css_selector(css_selector))
If you are just trying to switch to the frame based on the name attribute, then you can use this:
def frame_switch(name):
driver.switch_to.frame(driver.find_element_by_name(name))
To switch back to the main window, you can use
driver.switch_to.default_content()

Categories