I am making an Anki Addon that uses Pygame to allow the user to practice writing Japanese Kanji characters. Using the reviewer_did_show_question hook, when the question side of a card is shown to the user, a Pygame window will open that the user can draw inside of.
However, when moving from the overview state to the review state, the main window does not update, resulting in the Pygame window being open on the overview page, and the question card isn’t shown to the user. Only when the Pygame window is closed does the main window update and reveal the question.
This only occurs when moving from the overview state to the review state, and the addon is functional when moving from card to card.
Aside from the reviewer_did_show_question, I have also tried the following hooks: reviewer_did_show_answer - This works, however it means the Pygame window only shows once the answer is visible, which I don’t want state_did_change - Same problem as reviewer_did_show_question
Is there another hook/monkey patch that I can use to achieve the desired result while moving from the overview page to the review page?
I am also open to alternative solutions that don’t require the user to click a button/shortcut.
It sounds like an interesting project.
If I remember correctly PyGame UI has its own event loop that conflicts with Anki UI Qt event loop so it’s not very suitable for add-on use (maybe it causes the app to crash). So we probably need to make PyGame a separate app from Anki and communicate with it like AnkiConnect add-on.
But it might work if it already works when moving from card to card. (If you provide some sample code or a Github repository I might be able to figure it out.) If you have a PyGame window built into the add-on it seems that PyGame is modal and blocks Anki’s actions, but if so moving from card to card should not work either, so that’s strange.
I was not very thorough with my testing, but it appears Anki does not freeze/become unresponsive when moving from card to card while a Pygame window is active. Rendering text/images, playing audio, and interacting with the UI seemed functional. The only downside I observed was a decrease in performance, which I’m willing to accept. If upon further testing crashes or other strange side effects occur, I will look into AnkiConnect.
In different areas of Anki that I’ve tested, a Pygame window will freeze the main window, so I don’t know why moving from card to card is functional.
Moving “kanjiWritingPractice” to the background seems to work, I don’t know why. (Normally I think the UI needs to run in the main thread?)
Edit: Calling Anki’s UI from the background usually causes Anki to crash, but this PyGame window seems to work, strange.
# __init__.py
import threading
def kanjiWritingPractice_bg(a):
global mouse_pos, running
....
def kanjiWritingPractice(a):
t = threading.Thread(target=kanjiWritingPractice_bg, args=(a,), daemon=True)
t.start()
I think the safe way is to use PyQt6 instead of PyGame (the latest version of Anki uses PyQt6). PyQt6 is a GUI framework so it is possible to create paint apps using only PyQt6, and this is relatively easy since you don’t need to bundle PyGame into the add-on.
If you want to use PyGame and PyQt together for some reason you can probably do so by running PyGame’s event loop with PyQt6’s QTimer(PyGame’s widget updates are controlled by PyQt6). But I haven’t looked into this way in detail yet so I don’t know exactly how to do it. (I tried it briefly and it worked but there are many bugs.)
If both are difficult you can use pyinstaller or something similar to make a separate app that should work. In this case you can use AnkiConnect to communicate between the app and Anki. (Chrome extensions and web tools use a similar way.)