Jump to content

Qt for HarmonyOS/user development guide/a11y

From Qt Wiki
Revision as of 09:49, 26 August 2026 by Shawn Luo (talk | contribs) (Created page with "'''English''' 中文 = Enabling Qt Accessibility on HarmonyOS = In the Qt SDK releases currently provided, accessibility support on the HarmonyOS platform is disabled by default. To use or test accessibility, you have to enable it explicitly. == Enabling accessibility from the project template == <code>launchWant</code> holds the launch parameters of the Ability, and <code>io.qt.experimental.enableA11ySupport</code>...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

English 中文

Enabling Qt Accessibility on HarmonyOS

In the Qt SDK releases currently provided, accessibility support on the HarmonyOS platform is disabled by default. To use or test accessibility, you have to enable it explicitly.

Enabling accessibility from the project template

launchWant holds the launch parameters of the Ability, and io.qt.experimental.enableA11ySupport is the accessibility switch recognized by the Qt OHOS plugin.

Add the following to QAbility.ets:

private enableQtAccessibilitySupport(): void {
  this.launchWant.parameters = this.launchWant.parameters ?? {};
  this.launchWant.parameters['io.qt.experimental.enableA11ySupport'] = true;
}

Make sure it is called before Qt creates its window:

onWindowStageCreate(windowStage: Window.WindowStage) {
  this.enableQtAccessibilitySupport();
  qpa.handleAbilityOnWindowStageCreate(this, windowStage);
}

Keep it in place when the window stage is restored as well:

onWindowStageRestore(windowStage: Window.WindowStage): void {
  this.enableQtAccessibilitySupport();
  qpa.handleAbilityOnWindowStageRestore(this, windowStage);
}

Enabling accessibility when launching the HAP from the command line

Supported code versions

Branch Date
tqtc/harmonyos-5.12.12 2025/7/7
tqtc/harmonyos-5.15.16 2025/7/16

Launching

Add the launch parameter io.qt.experimental.enableA11ySupport to the want.

  • From the command line:
aa start -a QAbility -b com.ohos.ohosqttemplate --pb io.qt.experimental.enableA11ySupport true
  • From DevEco Studio: add --pb io.qt.experimental.enableA11ySupport true to the launch configuration.

Official Qt documentation

https://doc.qt.io/archives/qt-5.15/accessible-qwidget.html

SwitchButton derived from QAbstractButton

Custom widgets derived from QAbstractButton need no special handling.

class SwitchButton : public QAbstractButton {
    Q_OBJECT
    Q_PROPERTY(double offset READ offset WRITE setOffset)
    Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
public:
    explicit SwitchButton(QWidget* parent = nullptr);
    ~SwitchButton() override;

    QSize sizeHint() const override;
    QSize minimumSizeHint() const override;

    void setCheckedColor(const QColor& color);
    void setUncheckedColor(const QColor& color);
    void setDisabledColor(const QColor& color);
    void setHandleColor(const QColor& color);
    void setAnimationDuration(int duration);

protected:
    void paintEvent(QPaintEvent* event) override;
    void resizeEvent(QResizeEvent* event) override;

private:
    double offset() const;
    void setOffset(double value);
    QColor backgroundColor() const;
    void setBackgroundColor(const QColor& color);

    double m_offset;
    QColor m_checkedColor;
    QColor m_uncheckedColor;
    QColor m_disabledColor;
    QColor m_handleColor;
    QColor m_backgroundColor;
    QPropertyAnimation* m_animation;
    int m_handleRadius;
    int m_margin;
};

SwitchButton2 derived from QWidget

A custom widget derived directly from QWidget only gets a generic accessible description — no checked state and no actions. You have to derive from QAccessibleWidget, or reimplement QAccessibleActionInterface, and register a factory method with QAccessible::installFactory.

The HarmonyOS screen reader identifies switch-like widgets mainly through the following three items, so make sure all of them are implemented:

  • state().checkable — the widget can be checked
  • state().checked — whether it is currently checked
  • actionNames() contains toggleAction(), and doAction() handles it

The SwitchButton2 header:

class SwitchButton2 : public QWidget {
    Q_OBJECT
    Q_PROPERTY(double offset READ offset WRITE setOffset)
    Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable)
public:
    explicit SwitchButton2(QWidget* parent = nullptr);
    ~SwitchButton2() override = default;

    void setCheckable(bool);
    bool isCheckable() const;

    // Colors
    void setCheckedColor(const QColor& color);
    void setUncheckedColor(const QColor& color);
    void setDisabledCheckedColor(const QColor& color);
    void setDisabledUncheckedColor(const QColor& color);
    void setHandleColor(const QColor& color);
    void setDisabledHandleColor(const QColor& color);

    // State
    bool isChecked() const;

    // Animation duration
    void setAnimationDuration(int duration);

signals:
    void toggled(bool checked);

public slots:
    void setChecked(bool checked);
    void toggle();

protected:
    void paintEvent(QPaintEvent* event) override;
    void mousePressEvent(QMouseEvent* event) override;
    void mouseReleaseEvent(QMouseEvent* event) override;
    void resizeEvent(QResizeEvent* event) override;
    QSize sizeHint() const override;
    QSize minimumSizeHint() const override;
    double offset() const;
    void setOffset(double value);

private:
    bool m_checkable { true };
    bool m_checked { false };
    double m_offset { 0 };
    double m_radius { 0 };
    QColor m_checkedColor { Qt::green };
    QColor m_uncheckedColor { Qt::gray };
    QColor m_disabledCheckedColor { Qt::darkGreen };
    QColor m_disabledUncheckedColor { Qt::lightGray };
    QColor m_handleColor { Qt::white };
    QColor m_disabledHandleColor { Qt::gray };
    QPropertyAnimation* m_animation { nullptr };
    bool m_pressed { false };
};

main.cpp:

#include <QAccessible>
#include <QApplication>
#include <QtWidgets/qaccessiblewidget.h>

#include "mainwindow.h"
#include "switchbutton2.h"

class AccessibleSwitchButton : public QAccessibleWidget {
public:
    AccessibleSwitchButton(QWidget* w)
        : QAccessibleWidget(w)
    {
        Q_ASSERT(button());
        if (button()->isCheckable())
            addControllingSignal(QLatin1String("toggled(bool)"));
        else
            addControllingSignal(QLatin1String("clicked()"));
    }

    QAccessible::State state() const override
    {
        QAccessible::State state = QAccessibleWidget::state();
        SwitchButton2* b = button();
        if (b->isCheckable())
            state.checkable = true;
        if (b->isChecked())
            state.checked = true;
        return state;
    }

    QAccessible::Role role() const override
    {
        return QAccessible::Role::CheckBox;
    }

    QStringList actionNames() const override
    {
        QStringList names;
        if (widget()->isEnabled()) {
            names << toggleAction();
        }
        names << QAccessibleWidget::actionNames();
        return names;
    }

    void doAction(const QString& actionName) override
    {
        if (actionName == toggleAction()) {
            button()->toggle();
        } else {
            QAccessibleWidget::doAction(actionName);
        }
    }

protected:
    SwitchButton2* button() const
    {
        return qobject_cast<SwitchButton2*>(object());
    }
};

QAccessibleInterface* customWidgetFactory(const QString& classname, QObject* object)
{
    QAccessibleInterface* interface = 0;
    if (classname == QLatin1String("SwitchButton2") && object && object->isWidgetType())
        interface = new AccessibleSwitchButton(static_cast<QWidget*>(object));
    return interface;
}

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    QAccessible::installFactory(customWidgetFactory);
    MainWindow w;
    w.show();
    return a.exec();
}

Reusing simplewidgets_p.h

Qt already provides accessibility support for its basic widgets. If your own widget derives from QWidget but behaves like a basic widget such as a button or a label, you can reuse the accessible class Qt already implements.

However, these classes are not exported, so to reuse them you have to edit simplewidgets_p.h yourself and export the class you need (add Q_WIDGETS_EXPORT or Q_DECL_EXPORT to the header and rebuild).

For example QAccessibleButton (note that it sits inside a #if QT_CONFIG(abstractbutton) block — do not break that structure when exporting it):

class Q_WIDGETS_EXPORT QAccessibleButton : public QAccessibleWidget
{
    Q_DECLARE_TR_FUNCTIONS(QAccessibleButton)
public:
    QAccessibleButton(QWidget *w);

    QString text(QAccessible::Text t) const override;
    QAccessible::State state() const override;
    QRect rect() const override;
    QAccessible::Role role() const override;

    QStringList actionNames() const override;
    void doAction(const QString &actionName) override;
    QStringList keyBindingsForAction(const QString &actionName) const override;

protected:
    QAbstractButton *button() const;
};

Widgets with built-in accessibility support

The full list of Qt widgets that come with an accessible implementation can be found in src/widgets/accessible/qaccessiblewidgetfactory.cpp.

Qt widget Accessible class
QLineEdit QAccessibleLineEdit (except the internal line edit of a QSpinBox)
QTextEdit QAccessibleTextEdit
QPlainTextEdit QAccessiblePlainTextEdit
QComboBox QAccessibleComboBox
QAbstractSpinBox QAccessibleAbstractSpinBox
QSpinBox QAccessibleSpinBox
QDoubleSpinBox QAccessibleDoubleSpinBox
QScrollBar QAccessibleScrollBar
QAbstractSlider QAccessibleAbstractSlider
QSlider QAccessibleSlider
QToolButton QAccessibleToolButton
QCheckBox / QRadioButton / QPushButton / QAbstractButton QAccessibleButton
QDialog / QMessageBox / QToolBar / QFrame QAccessibleWidget
QMainWindow QAccessibleMainWindow
QLabel / QLCDNumber / QStatusBar / QTipLabel QAccessibleDisplay
QProgressBar QAccessibleProgressBar
QMenuBar QAccessibleMenuBar
QMenu QAccessibleMenu
QTreeView QAccessibleTree
QTableView / QListView QAccessibleTable
QTabBar QAccessibleTabBar
QStackedWidget QAccessibleStackedWidget
QGroupBox QAccessibleGroupBox
QToolBox QAccessibleToolBox
QDialogButtonBox QAccessibleDialogButtonBox
QDial QAccessibleDial
QTextBrowser QAccessibleTextBrowser
QAbstractScrollArea QAccessibleAbstractScrollArea
QScrollArea QAccessibleScrollArea
QCalendarWidget QAccessibleCalendarWidget
QDockWidget QAccessibleDockWidget
QMdiArea QAccessibleMdiArea
QMdiSubWindow QAccessibleMdiSubWindow
QSplitter / QSizeGrip / QSplitterHandle / QRubberBand QAccessibleWidget
QWidget QAccessibleWidget

Note: if your custom widget derives from any of the Qt widgets above, the matching accessible implementation is picked up automatically along the base class chain — no extra work is needed.

Third-party Qt widget libraries

Refer to the documentation of the respective widget library.