Tracking Circular shift in list after drag and drop on screen

rearrange the options on the screen by dragging to their correct position

#the initial position of the options is dictionary opt_pos

the desired order is myrespo

#the problem is e.g. when “C” is dragged to the position of “A” , circular shif will take place on the screen.

the code need follow or track where each options shifted and move to their shifted position and rearrange them according to myrespo list

testimg

        opt_pos = {"A": (100, 200), "B": (300, 400), "C": (500, 600), "D": (700, 800)}
                 
        myrespo = ["C", "B", "D", "A"]
        
        tracking = {}
        for index, goto in enumerate(myrespo):
            if index == 0:
                pyautogui.moveTo(opt_pos[goto])
                pyautogui.dragTo(opt_pos["A"], duration=0.4)
                if goto == "A":
                    tracking["A"] = opt_pos["A"]
                    tracking["B"] = opt_pos["B"]
                    tracking["C"] = opt_pos["C"]
                    tracking["D"] = opt_pos["D"]
                elif goto == "B":
                    tracking["A"] = opt_pos["B"]
                    tracking["B"] = opt_pos["A"]
                    tracking["C"] = opt_pos["C"]
                    tracking["D"] = opt_pos["D"]
                elif goto == "C":
                    tracking["A"] = opt_pos["C"]
                    tracking["B"] = opt_pos["A"]
                    tracking["C"] = opt_pos["B"]
                    tracking["D"] = opt_pos["D"]
                elif goto == "D":
                    tracking["A"] = opt_pos["D"]
                    tracking["B"] = opt_pos["A"]
                    tracking["C"] = opt_pos["B"]
                    tracking["D"] = opt_pos["C"]
            elif index == 1:
                pyautogui.moveTo(tracking[goto])
                pyautogui.dragTo(opt_pos["B"], duration=0.4)
                if goto == "A":
                    print("skipped")
                elif goto == "B":
                    print("skipped")
                elif goto == "C":
                    tracking["B"] = opt_pos["C"]
                    tracking["C"] = opt_pos["B"]
                elif goto == "D":
                    tracking["B"] = opt_pos["D"]
                    tracking["C"] = opt_pos["B"]
                    tracking["D"] = opt_pos["C"]
            elif index == 2:


                pyautogui.moveTo(tracking[goto])
                pyautogui.dragTo(opt_pos["C"], duration=0.4)


        pyautogui.moveTo(opt_pos["submit"])
        pyautogui.click()

I don’t understand the problem. Can you describe what effect you want to achieve, what is actually happening and why that is a problem?

  1. i want to drag and arrange the options on the image according to myrespo list
  2. the opt_pos list a x,y cordinate where i will go and grab each options
  3. the problem is after performing the first drag, the position of the options will change and when i try to arrange the second option, am unable to move to and grab the right option because it has moved from its initial place, that why i wanted to track and follow where each options has moved

Ah, ok. Makes sense. And after the first drag, the old top menu item automatically shifts to the bottom place? This is what you mean by a circular shift?

Exactly, that’s what is happening
for example: if i drag “C” into the position of “A”, then the old “A” will move down to the position of “B” and the old “B” will move down to the position of “C”, “D” is not affected by this case.

Ok - so, it is not an automatic circular shift. “A” is just pushed down, when “C” is dragged to the top – which is what I had expected, since this is how almost all draggable items behave in those kind of contexts.
Ok - your problem is tricky because you are sort of iterating over something while at the same time changing that container…

Yes Sir, there has to be a way to do track each pushed down containers.

It’s indeed tricky. So, you do have to track the changes in the container somehow. The most simple solution I can think of is something like this:

# use indices to indicate the menu item relative positions, do not use labels of the menu itself
# so `pos` will not have to change - for instance
pos = {0: (100, 200), 1: (100, 300), 2: (100, 500), 3: (100, 700)}
 
def move(index: int, label: str, labels: list[str]):
    # move `label` to relative position at `index`
    # `labels` represents the current menu labels, in order
    old_index = labels.index(label)
    if old_index != index:
        moveTo(pos[old_index])
        dragTo(pos[index], duration=0.4)
        # now you need to reflect the on-screen change
        # the list of labels is changed in-place 
        labels.remove(label)
        labels.insert(index, label)

def permutate(old_order: list[str], new_order: list[str]):
    labels = new_order[:]
    for index, label in enumerate(old_order):
        move(index, label, labels)

Hope this works - I don’t have the pyautogui package, so was not able to really test.

There is a bug in the above code. In the permutate function the loop needs to be over the new_order, like this:

def permutate(old_order, new_order):
    labels = old_order[:]
    for index, label in enumerate(new_order):
        move(index, label, labels)
    assert labels == new_order

To be called as

permutate(list("ABCD"), list("CBDA"))

Wow, it works more faster, and more accurately, Thanks Sir!, i appreciate it