Kyle Rego

Figuring out .ui files in an Anki add-on

When I was looking into adding some new features to an existing Anki add-on, I had to make sense of some files with the .ui extension that had some Qt XML. The conclusion I got to is these are edited using Qt Creator (I installed Qt Creator 12.0.2 Community) and compiled into Python code using a User Interface Compiler. From reading the add-on source and Qt docs, I noticed an idiom for using the compiled Python.

If you have one of these files and want to make changes, install Qt Creator and open the file. From there you can design the UI:

Image showing Qt Creator and editing a .ui file

On the left are all different types of Qt Widgets (and other types like layouts) that you can drag and drop onto the UI. On the right, you can see the object tree and edit attributes like objectName and stuff.

I was just editing a small .ui file that I made the other day to figure this out the first time:

Image showing Qt Creator and editing a .ui file

XML code in the saved .ui file:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>LapseReviewRatioWidget</class>
 <widget class="QWidget" name="LapseReviewRatioWidget">
 ...
 ...
 ...

Use pyuic6 to compile the .ui file into Python:

pyuic6 -o lapse_review_ratio_form.py lapse_review_ratio_form.ui

That gives us the Python code:

# Form implementation generated from reading ui file 'lapse_review_ratio_form.ui'
#
# Created by: PyQt6 UI code generator 6.4.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt6 import QtCore, QtGui, QtWidgets


class Ui_LapseReviewRatioWidget(object):
    def setupUi(self, LapseReviewRatioWidget):
        LapseReviewRatioWidget.setObjectName("LapseReviewRatioWidget")
        LapseReviewRatioWidget.resize(319, 109)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        ...
        ...
        ...

The idiom for using this (some kind of import Ui_LapseReviewRatioWidget is also necessary):

class LapseReviewRatioWidget(QWidget):
    def __init__(self, flags):
        """
        Widget for lapse review ratio options
        """
        super().__init__(parent=None, flags=flags)
        self.ui = Ui_LapseReviewRatioWidget()
        self.ui.setupUi(self)

Also see Using a Designer UI File in Your Qt for Python Application

This project is maintained by KyleRego