Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Интеграция C в QML

Anna | 24.06.2014 | нет комментариев

Язык QML для Qt Quick разрешает c легкостью делать многие вещи, исключительно что касается анимированных пользовательских интерфейсов. Впрочем, не всё допустимо сделать либо не всё подходит под реализацию в QML, в частности:

  • приобретение доступа к функциональности извне окружения QML/Javascript
  • реализация скептических по продуктивности функций, где требуется нативный код для возрастания результативности
  • огромный либо трудный не декларативный код, тот, что было бы изнурительно реализовывать в JavaScript

Как Вы увидите позднее, Qt легко отображает C код для QML. В этой статье мы сотворим маленькое, но функциональное приложение, делающее это. Пример написан для Qt 5 и использует компоненты Qt Quick, следственно для запуска примера Вам нужен как минимум Qt 5.1.0.

Обзор

Базовые шаги, для того, Дабы показать тип C , с его свойствами, способами, сигналами и слотами, окружению QML:

  • определение нового класса, унаследованного от QObject
  • помещение макроса Q_OBJECT в объявление класса для поддержки сигналов, слотов и прочих сервисов метаобъектной системы Qt
  • объявление свойств, применяя макрос Q_PROPERTY
  • вызов qmlRegisterType() в C коде приложения для регистрации типа в Qt Quick движке

Подробности находятся в разделе документации Qt Отображение признаков C для QML и в туториале Создание растяжений C для QML.

Генератор SSH ключей

Для примера, сотворим малое приложение, которое будет генерировать пару открытого/закрытого SSH ключей, с поддержкой GUI. Пользователю будут предоставлены элементы управления для соответствующих параметров, после этого будет запущена программа ssh-keygen для генерации пары ключей.

Мы реализуем пользовательский интерфейс, применяя новые элементы управления Qt Quick, посколько это было задумано как настольное приложение. Изначально, для приобретения навыка взаимодействия, запустим qmlscene с начальным кодом QML. Скриншот показан ниже:

Пользовательский интерфейс запрашивает пользователя данные о типе ключа, имени файла для генерируемого приватного ключа и, опционально, секретную фразу, которая должна быть подтверждена.

C класс

Сейчас, имея интерфейс, нам нужно реализовать внутреннюю функциональность. Мы не можем вызвать внешнюю программу напрямую из QML, следственно мы обязаны написать это на C (что есть целью нашего приложения).

Сперва, определим класс, инкапсулирующий функционал для генерации ключа (он будет отображен как новейший класс KeyGenerator в QML). Это сделано в заголовочном файле KeyGenerator.h:

#ifndef KEYGENERATOR_H
#define KEYGENERATOR_H

#include <QObject>
#include <QString>
#include <QStringList>

// Simple QML object to generate SSH key pairs by calling ssh-keygen.

class KeyGenerator : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString type READ type WRITE setType NOTIFY typeChanged)
    Q_PROPERTY(QStringList types READ types NOTIFY typesChanged)
    Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged)
    Q_PROPERTY(QString passphrase READ filename WRITE setPassphrase NOTIFY passphraseChanged)

public:
    KeyGenerator();
    ~KeyGenerator();

    QString type();
    void setType(const QString &t);

    QStringList types();

    QString filename();
    void setFilename(const QString &f);

    QString passphrase();
    void setPassphrase(const QString &p);

public slots:
    void generateKey();

signals:
    void typeChanged();
    void typesChanged();
    void filenameChanged();
    void passphraseChanged();
    void keyGenerated(bool success);

private:
    QString _type;
    QString _filename;
    QString _passphrase;
    QStringList _types;
};
#endif

Нам нужно наследовать наш класс от QObject. Мы объявляем все свойства, которые нам необходимы и все связанные с ними способы, способы уведомлений становятся permark! text: qsTr(“Key type:”) } ComboBox { id: combobox Layout.fillWidth: true model: keygen.types currentIndex: 2 } } // Filename RowLayout { Label { text: qsTr(“Filename:”) } TextField { id: filename implicitWidth: 200 onTextChanged: updateStatusBar() } Button { text: qsTr(“&Browse…”) onClicked: filedialog.visible = true } } // Passphrase RowLayout { Label { text: qsTr(“Pass phrase:”) } TextField { id: passphrase Layout.fillWidth: true echoMode: TextInput.Password onTextChanged: updateStatusBar() } } // Confirm Passphrase RowLayout { Label { text: qsTr(“Confirm pass phrase:”) } TextField { id: confirm Layout.fillWidth: true echoMode: TextInput.Password onTextChanged: updateStatusBar() } } // Buttons: Generate, Quit RowLayout { Button { id: generate text: qsTr(“&Generate”) onClicked: keygen.generateKey() } Button { text: qsTr(“&Quit”) onClicked: Qt.quit() } } } FileDialog { id: filedialog title: qsTr(“Select a file”) selectMultiple: false selectFolder: false nameFilters: [ "All files (*)" ] selectedNameFilter: “All files (*)” onAccepted: { filename.text = fileUrl.toString().replace(“file://”, “”) } } KeyGenerator { id: keygen filename: filename.text passphrase: passphrase.text type: combobox.currentText onKeyGenerated: { if (success) { status.text = qsTr(‘<font color=”green”>Key generation succeeded.</font>’) } else { status.text = qsTr(‘<font color=”red”>Key generation failed</font>’) } } } function updateStatusBar() { if (passphrase.text != confirm.text) { status.text = qsTr(‘<font color=”red”>Pass phrase does not match.</font>’) generate.enabled = false } else if (passphrase.text.length > 0 && passphrase.text.length < 5) { status.text = qsTr(‘<font color=”red”>Pass phrase too short.</font>’) generate.enabled = false } else if (filename.text == “”) { status.text = qsTr(‘<font color=”red”>Enter a filename.</font>’) generate.enabled = false } else { status.text = “” generate.enabled = true } } Component.onCompleted: updateStatusBar() }
Приведенный выше код немножко огромный, впрочем, огромная часть работы связана с расстановкой компонентов GUI. Данный код должен быть предельно простым, Дабы двигаться дальше.

Подметьте, что мы импортируем com.ics.demo версии 1.0. Скоро, мы увидим, где возникает имя этого модуля. Это делает новейший QML тип KeyGenerator доступном и мы объявляем его экземпляр. Имея доступ к его C свойствам, как к QML свойствам, дозволено вызывать его способы и трудиться с сигналами, как это сделано сonKeyGenerated.

Больше полное приложение следует делать с дополнительными проверками ошибок и осмысленными уведомлениями об ошибках, если генерация ключа была неудачной (мы могли бы легко добавить новейший способ либо качество для этого). Пользовательский интерфейс также дозволено усовершенствовать, делая его больше эластичным.

Наша основая программа, является, по сути, враппером, таким как qmlscene. Всё что нам нужно, это зарегистрировать наш тип, для доступа к нему в движке QML:

qmlRegisterType<KeyGenerator>("com.ics.demo", 1, 0, "KeyGenerator");

Это делает C тип KeyGenerator доступным как QML тип KeyGenerator, в модуле com.ics.demo версии 1.0, тот, что будет импортирован.

Как правило, для запуска QML кода из исполняемого файла, в основной программе Вы создаете QGuiApplicationи QQuickView. Теперь же, для применения компонентов Qt Quick нужно немножко дополнительной работы, если элемент верхнего яруса ApplicationWindow либо Window. Вы можете посмотреть начальный код, как это реализуется. Это урезанная версия qmlscene, нужный минимум для примера.

Вот полный листинг основной программы, main.cpp:

#include <QApplication>
#include <QObject>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQuickWindow>
#include <QSurfaceFormat>
#include "KeyGenerator.h"

// Main wrapper program.
// Special handling is needed when using Qt Quick Controls for the top window.
// The code here is based on what qmlscene does.

int main(int argc, char ** argv)
{
    QApplication app(argc, argv);

    // Register our component type with QML.
    qmlRegisterType<KeyGenerator>("com.ics.demo", 1, 0, "KeyGenerator");

    int rc = 0;

    QQmlEngine engine;
    QQmlComponent *component = new QQmlComponent(&engine);

    QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));

    component->loadUrl(QUrl("main.qml"));

    if (!component->isReady() ) {
        qWarning("%s", qPrintable(component->errorString()));
        return -1;
    }

    QObject *topLevel = component->create();
    QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);

    QSurfaceFormat surfaceFormat = window->requestedFormat();
    window->setFormat(surfaceFormat);
    window->show();

    rc = app.exec();

    delete component;
    return rc;
}

Если это не видимо, при применении модулей, написанных на C , с QML, Вы не можете применять программуqmlscene, потому что C код не будет слинкован. Если же Вы испробуете это, то получите сообщение об ошибке, что модуль не установлен.

Итоги

Данный пример показывает, как легко дозволено создавать новые QML компоненты на C и отображать свойства, сигналы и слоты. Правда многое дозволено сделать с QML, C по бывшему пригоден и, как правило, будет использован в сочетании с QML в любом не банальном приложении.

Вы можете скачать каждый начальный код примера отсель.

 

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB