Force Selections to visually update?

Hiya! I’m doing something very stupid :3 It’s going very well, I’ve bashed my head into and through several dozen walls to create a plugin that shouldn’t exist, it’s great.

One minor annoyance that I’d like to fix, though, and it’s one of those things that seems like it should be simple to fix and is probably actually a nightmare to hunt down unless you already know what you’re doing.

I should explain. My code is messing with the active selection, like a lot, like moving and resizing it multiple times in a single action. I’ve kludged my way to making it work for what I need to do - It’s not pretty, but it’s fine.

One minor issue. The currently active selection, it seems to, uh… Stay stuck visually at the last place it was after any given action, even though it’s actually at the correct new place logically.

This makes it kind of hellish to actually use as a keyboard that I’m typing with, especially if I want to go back and correct something. Yes, I made a keyboard that slaps pixel data directly into the canvas, do not ask why. (Okay, you can, but it’s not super relevant to this initial explanation.)

Basically - Is there a line of code I can cram through Krita to make it play nice with my selection jogging shenanigans? To correctly align the visual display of the selection with where it actually, currently is? Or, maybe, am I possibly handling selections incorrectly, and if I were handling them correctly, this wouldn’t be an issue? Really hoping for the former, but the latter will suffice.

Also, uh, side note - why are the official Krita API docs down? Super annoying.

Looks up to me Krita - Krita Painting application

1 Like

Welp. I don’t know why Google and the tutorials I was scuttling through didn’t point here, but maybe they’re out of date. I could NOT find that, to the point that the moment I saw your reply, I bookmarked the link XD

Thanks much, at any rate, that will probably help immensely.

Most search engines didn’t update their index yet, it seems, and it also doesn’t help that a lot of the links in the scripting sections and in the manual are also not up to date.

After you do your selection manipulation try triggering two invert_selection actions like shown in this post. It’s not an ideal solution unfortunately.

In the API none of these will update visually (using setSelection)

dilate
erode
border
feather
grow
shrink
smooth
invert

These do though

selectAll
replace
select
subtract
intersect
resize
contract
move

Try uncommenting bits of this to see how they work, im not clear on how all of them work.

def func():
    import time
    from krita import Selection

    start_time = time.time()

    #---
    
    inst = Krita.instance()
    doc = inst.activeDocument()
    if not doc: return

    node = doc.activeNode()
    
    sel = doc.selection()
    new_sel = Selection()

    if sel:
        new_sel.replace(sel)

    # if not sel:
    #     print("No selection...")
    #     return

    #----------------------
    # does not update visually
    #----------------------

    # [new_sel.dilate() for i in range(10)]
    # [new_sel.erode() for i in range(10)]
    # new_sel.border(5,10)
    # new_sel.feather(10) # can't be visualized with ants anyway
    # new_sel.grow(10,25)
    # new_sel.shrink(5,10,0)
    # new_sel.smooth() # can't be visualized with ants anyway
    # new_sel.invert() #not the same as the action

    #----------------------
    # updates visually
    #----------------------

    all_sel = Selection()
    # selects bounding box of all pixels in a node (even outside canvas area)
    all_sel.selectAll(node,255)
    new_sel.replace(all_sel)

    # sub_sel = Selection()
    # sub_sel.select(0,0,200,400,255)
    # new_sel.subtract(sub_sel)

    # int_sel = Selection()
    # int_sel.select(0,0,200,400,255)
    # new_sel.intersect(int_sel)

    # new_sel.resize(100,100) # not sure how this is upposed to work
    
    # new_sel.select(0,0,25,25,255) #select box in top left

    # new_sel.contract(100) # confusing

    # new_sel.move(0,100)

    # dup_sel = new_sel.duplicate() # idk
    # doc.setSelection(dup_sel)

    #---

    doc.setSelection(new_sel)

    #---
    # workaround: using this action to invert the selection twice forces an update
    # inst.action("invert_selection").trigger()
    # inst.action("invert_selection").trigger()

    #---
    
    end_time = time.time()
    elapsed_time = (end_time - start_time) * 1000  # Convert to milliseconds
    print(f"Function executed in {elapsed_time:.2f} milliseconds")

func()
1 Like

Yeah, that totally works perfectly for my kludgy little script. I now have a wake_up_ants() function in my script:

def wake_up_ants(self):
	Krita.instance().action("invert_selection").trigger()
	Krita.instance().action("invert_selection").trigger()

And I’ve just chucked that in at the end of each of the two functions I have that handle all the selection changes:

def print_glyph(self, cut_dot_array):
	document = Krita.instance().activeDocument()
	selection = document.selection()
	tempSelection = selection.duplicate()
	for dotx in cut_dot_array:
		cut1 = Selection()
		cut1.select(selection.x(), selection.y() + (dotx * 2), 2, 2, 255)
		tempSelection.subtract(cut1)
	document.setSelection(tempSelection)
	
	Krita.instance().action("fill_selection_foreground_color").trigger()
			
	document.setSelection(selection)
	self.wake_up_ants()
	document.waitForDone()

def shift(self, amount):
	document = Krita.instance().activeDocument()
	selection = document.selection()
	selection.move(amount,0)
	self.wake_up_ants()
	document.waitForDone()

There’s, uh. Probably some of this I could clean up, I probably don’t need all the document.waitForDone() calls. But I’ll save code cleanup for another day, I’m just happy I don’t have to strain my brain thinking one move back in time all the time.

This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.