lonm<p><strong>Krita Quick Commands</strong></p><p>I use quick commands a lot in Vivaldi, IDEs, basically any complex app with a lot of commands. They’re a great way to learn what the app can do, an easy way to find less frequently used commands than hunting through a menu, and give you a quick reminder of the command’s keyboard shortcut when you want to learn what that is. I wanted to build a script to add this functionality to the digital painting app Krita. This blog post discusses my journey.</p><p><strong>Quick Commands</strong></p><p>Here’s what the final result looks like, and you can find the script for it <a href="https://gist.github.com/LonMcGregor/779be4a2fcd334346e2b26e495882af6" rel="nofollow noopener noreferrer" target="_blank">here</a>.</p> <p>It has a search box where you type roughly what you want, and then it will show the results in a list. You can navigate around using the up and down keys, and when you press enter, your action gets executed. You can press Esc to close it if you decide you don’t want to do anything.</p><p>I decided to filter on the command text and the tooltip text for each action,. Most actions don’t have detailed tooltip text in Krita, but some of the more complex or obscure ones do, and this is designed to let you search through them as well in case you can’t remember the exact name of a particular action command. Filtering is done on individual words so if you know you remember two words but not the order they appear in exactly, it will offer some leeway.</p><p>I’ve added this script to my Krita setup and given it the shortcut F1. I don’t need a keyboard button to open a webpage that I can keep as a bookmark, and this is much more helpful for quickly accessing different commands.</p><p><strong>Writing the Script</strong></p><p>Krita’s scripting environment is a bit tricky to use. It has an incredibly basic built-in editor, with an output window when things run. So you are limited to basic print methods for debugging. The scripting tutorials offer a decent introduction, though for anything more complex you will need to look at API documentation. My script builds a simple interface using the PyQt5 library to connect to Krita’s Qt based UI. There are 3 places I looked for documentation:</p><ul><li>The Krita C++ API – Good documentation from the source code</li><li>The Qt C++ API – Very detailed, discusses how to use their library</li><li>The PyQt5 API – This documentation isn’t</li></ul><p>My big problem with the PyQt5 library’s documentation is that it’s not really documentation more than it is a list of methods and classes. The vast majority of the text that should explain how it works and how to use it merely contains the text ‘TODO’. Given that Qt5 is being replaced by Qt6, I guess that’s never going to be fixed.</p><p>Having done some UI stuff before, figuring out the right widgets to use, and what the methods might mean from context was simple enough, though some explanations or even screenshots would have been nice. I fell back to the Krita extension documentation for advice on how to set up a basic UI, because doing that solely from the PyQt5 documentation was clearly not going to work.</p><p>I had not used signals in Python recently, so I needed some help, and the PyQt5 documentation helpfully offered none whatsoever, other than a basic explanation of how to connect things generally. It does have a list of places you can connect to,but no visible examples of how that actually works. Thankfully, the Krita application comes with some built-in extension scripts that demonstrate how to use this, so I was able to learn from there. Presented with an example, I can now see the PyQt5 approach to signals is fairly analagous to how other languages and APIs use listeners:</p><pre><code>def onTextChanged(newtext): ...textbox = QLineEdit()textbox.textChanged.connect(onTextChanged)</code></pre><p>A major problem with how the PyQt5 library is set up is that the python packages you need to import from are totally disorganised an unclear. If you want widgets you must import <code>from PyQt5.QtWidgets</code>, but if you want to access enumerated values like keyboard key IDs, you need to import <code>from PyQt5.QtCore.Qt</code>, and even then you don’t need to use the <code>Key</code> enum, they’re all accessible with a name like <code>Qt.Key_Up</code>. Figuring this out from the documentation was very difficult for me, so I needed again to fall back to a provided example from Krita.</p><p>Krita launches it’s actions using a named ID. These are all listed on the Krita scripting tutorial page, but I needed to access these programatically. Reading through the Krita and Qt APIs showed it was pretty easy where the actions could all be listed, but I did have sometrouble identifying the right place where the action ID is stored. The Krita action dictionary calls these ‘id’s, but they are in Qt ‘object names’. Eventually I found these are not accessed as properties but rather by a getter function:</p><pre><code>from krita import Kritamykrita = Krita.instance()allkritacmds = mykrita.actions()...command_id = kritacmd.objectName()</code></pre><p>The script I ended up with could probably be made more efficient, but I enjoyed the exercise of learning how to interact with Krita’s scripting environment.</p><p><a href="https://lonm.vivaldi.net/2025/05/29/krita-quick-commands/" class="" rel="nofollow noopener noreferrer" target="_blank">https://lonm.vivaldi.net/2025/05/29/krita-quick-commands/</a></p><p><a rel="nofollow noopener noreferrer" class="hashtag u-tag u-category" href="https://lonm.vivaldi.net/tag/documentation/" target="_blank">#documentation</a> <a rel="nofollow noopener noreferrer" class="hashtag u-tag u-category" href="https://lonm.vivaldi.net/tag/extension/" target="_blank">#extension</a> <a rel="nofollow noopener noreferrer" class="hashtag u-tag u-category" href="https://lonm.vivaldi.net/tag/krita/" target="_blank">#krita</a> <a rel="nofollow noopener noreferrer" class="hashtag u-tag u-category" href="https://lonm.vivaldi.net/tag/python/" target="_blank">#python</a> <a rel="nofollow noopener noreferrer" class="hashtag u-tag u-category" href="https://lonm.vivaldi.net/tag/qt/" target="_blank">#qt</a> <a rel="nofollow noopener noreferrer" class="hashtag u-tag u-category" href="https://lonm.vivaldi.net/tag/scripting/" target="_blank">#scripting</a> <a rel="nofollow noopener noreferrer" class="hashtag u-tag u-category" href="https://lonm.vivaldi.net/category/software/" target="_blank">#Software</a> </p>