Switch to Alternate Version of Brush Plugin

This plugin adds a shortcut to switch between brush preset that has the similar name (any brush preset with a shared name before “[”, “Paintbrush”, “Paintbrush [1]”, “Paintbrush [2]”, “Paintbrush [Wet]”). The brush name before “[” or " [" have to be the same.

The original purpose of this plugin was to change between different brush angle. Since apparently changing brush tip angle via python is not possible. I made this plugin to switch between the brush preset and its duplicates with different brush tip angles.

“Watercolor [90deg]”
“Watercolor [180deg]”

Why switching brush angle?
While Krita&MyPentab have brush tilt useful when you want to change the brush angle subtly, but when you want to tilt 60 degrees up you have to rotate the view, or proceed with an awkward posture.
in reality, I often change how I hold my brush/pencil, so I don’t have to move my elbow all the way when I want to rotate my pencil 90 degrees or roll it to 180 degrees.

But you can use this plugin how you see fit, maybe switching between the brush blending mode, shapes, or anything.

“Paintbrush [Wet]”, “Paintbrush [Dry]”
“Paintbrush [Square]”, “Paintbrush [Textured]”
“MyBrushes [Brush 01]”, “Paintbrush [Brush 02]”

This is my first plugin. I have no experience in phyton, only have web dev programming and little unity3d programming experience. This plugin may be not well written. I hope it will work, and you find this useful.


so cool, its a great implement to brushes collection.

HI! im trying to use the plugin and don’t work.
maybe there’s some i m not understanding. I have “wojtryb6_N_24_knife” i modify it and rename to “wojtryb6_N_24_knife [1]” and don’t work.
Its correct what i did?

This plugin is basically “next favourite preset shortcut” but instead of switching between presets in favourite tags, it switches between brush that has a similar name with the selected brush preset. so both “wojtryb6_N_24_knife” and “wojtryb6_N_24_knife [1]” have to exist.

of course you have to set a keys to the keyboard shortcut “Configure Krita>Keyboard Shortcut>Scripts>SwitchBrushAlternative”

in the latest version, presets will share opacity and size when switching, unless you turn it off in “tool>scripts”. or having letter “o” or “s” in the second brackets in its name to disable opacity ("<brushname> [<anything>] [os]" < this will disable opacity and size sharing for this preset.)


it works some times, with simple names, but with other no and also appear this error:
Python 3.8.1: /usr/bin/python3
Sun Jan 3 12:03:16 2021

A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.

/home/chancho/.local/share/krita/pykrita/sb_alternative/init.py in on_sb_alternative_next_trigger()
53 lastPreset = pp
54 presetFound = True
56 if nextPreset == None : nextPreset = firstPreset
57 if prevPreset == None : prevPreset = lastPreset
nextPreset undefined
firstPreset undefined

/home/chancho/.local/share/krita/pykrita/sb_alternative/init.py in alternateBrush(self=<sb_alternative.SwitchBrushAlternative object>)
43 if sp == ss :
44 if firstPreset == None : firstPreset = pp
45 if presetFound == False :
46 prevPreset = pp
47 else :
presetFound = False
KeyError: None
cause = None
class = <class ‘KeyError’>
context = None
delattr = <method-wrapper ‘delattr’ of KeyError object>
dict = {}
dir =
doc = ‘Mapping key not found.’
eq = <method-wrapper ‘eq’ of KeyError object>
format =
ge = <method-wrapper ‘ge’ of KeyError object>
getattribute = <method-wrapper ‘getattribute’ of KeyError object>
gt = <method-wrapper ‘gt’ of KeyError object>
hash = <method-wrapper ‘hash’ of KeyError object>
init = <method-wrapper ‘init’ of KeyError object>
init_subclass =
le = <method-wrapper ‘le’ of KeyError object>
lt = <method-wrapper ‘lt’ of KeyError object>
ne = <method-wrapper ‘ne’ of KeyError object>
new =
reduce =
reduce_ex =
repr = <method-wrapper ‘repr’ of KeyError object>
setattr = <method-wrapper ‘setattr’ of KeyError object>
setstate =
sizeof =
str = <method-wrapper ‘str’ of KeyError object>
subclasshook =
suppress_context = False
traceback =
args = (None,)
with_traceback =

The above is a description of an error in a Python program. Here is
the original traceback:

Traceback (most recent call last):
File “/home/chancho/.local/share/krita/pykrita/sb_alternative/init.py”, line 55, in on_sb_alternative_next_trigger
File “/home/chancho/.local/share/krita/pykrita/sb_alternative/init.py”, line 45, in alternateBrush
if presetFound == False :
KeyError: None

and in this moment work!!! wtf!!!

This is an excellent plugin, great idea, simple to use, huge timesaver! Thank you so much for creating and sharing! I hope that you will continue to maintain it and maybe even further develop it… BR

1 Like

this is as useful to me as the Ten Brush plugin. Ten Brush was merged, likewise, i could see Switch to Alternate get merged into Krita.
Along with some enhancements that show how it is a more prominent part of Krita.

When this plugin is activated, there could be some recommendations […] for what to append on the brushe’s name. like [1] [2] [3] maybe [o] [s] [os] etc
what other things can you think of that can make this a more integral part of Krita.
Sort brushes in a tag next to their alternate brush.

How about an Alternate Switch Set creator. Where you can drag brushes you want save them as copy with a desired name. And then, before completing, place them in a tag of choice.

Nice! How do I use this? Or is there a newer plugin?

It’s the latest. Just create a tag with brushes you want and add brackets to brush inside this tag you want to switch to when pressing key.

Okay, but where do I put the files?

Oh, you can do so manually if on Windows you have to paste the contents in the pykrira folder located in the hidden folder in the user’s Document folder. So you have to unhide.

Or to another way is go in krita to open ressource folder.

I believe there’s even a plugin to import plugin

Awesome, thanks! (I use arch BTW)

Tools → Scripts → Import Python Plugin from… should handle that without you having to do it manually. You just either provide an URL or a downloaded zip and it works, I think (I haven’t tested it but it was made to work).

@tachiko ^