Qt_QML

本文探讨了QML和QWidget在用户界面设计上的不同适用场景,并详细介绍了QML的基本概念、构建方式、属性设置、国际化等核心内容,以及如何在QML中使用数据模型进行视图展示。

Common 

QWidgets were designed for a different type of user interface than QML, so it is not always a good idea to port a QWidget-based application to QML. 

QWidgets are a better choice if your UI is comprised of a small number of complex and static elements, 

QML is a better choice if your UI is comprised of a large number of simple and dynamic elements.


Basic concept 

> QDeclarativeView

QDeclarativeItem objects can be placed on a standard QGraphicsScene and displayed with QGraphicsView. 

QGraphicsView subclass, for displaying QML files, connecting between QML and C++ Qt objects.

>QGraphicsItem, QGraphicsObject 


QML building 

>Build in VC

QML added into qrc, need rebuild because it is part of the dll

If only use the relative path, it can be dynamically loaded.


Properties 

[default] property <type> <name>[: defaultValue]

>example 

property bool activatedOnce: false

property string launchAppTxt: qsTr("Launch Application")

property int current: 0

property alias dataModel: grid.model

property variant target


Localization 

    // There is a bug in QML that we can't use qsTr in listElement. So we use QT_TR_NOOP

    // http://bugreports.qt.nokia.com/browse/QTBUG-11403 

QT_TR_NOOP("Filename");

qsTr(), qsTranslate(), QT_TR_NOOP(), QT_TRANSLATE_NOOP()

http://www.developer.nokia.com/Community/Wiki/QML%E5%9B%BD%E9%99%85%E5%8C%96%E2%80%94%E2%80%94%E4%B8%AD%E6%96%87%E7%A4%BA%E4%BE%8B 

--Common End---


Binding 

C++ binding 

>setSource by QUrl

QDeclarativeView *qmlView = new QDeclarativeView;

 qmlView->setSource(QUrl::fromLocalFile("myqml.qml"));

 QWidget *widget = myExistingWidget();

 QVBoxLayout *layout = new QVBoxLayout(widget);

 layout->addWidget(qmlView);


>setSource by QRC

setSource(QUrl("qrc:NotificationHubView.qml"));


>qmlRegisterUncreatableType

 registers the C++ type in the QML system with the name qmlName

 qmlRegisterUncreatableType<LaunchPadViewImp>("AdLaunchPadUI", 1, 0, "LaunchPadViewImp", "Cannot create LaunchPadViewImp in QML");


Tips 

> QMetaType

for unregistered datatype, can't instantiate abstract class 

Q_DECLARE_METATYPE / qRegisterMetaType


Context 

Contexts allow data to be exposed to the QML components instantiated by the QML engine.

>setContextObject( QObject * object )

Create a Context Class, we can use the Context Class's Property in QML, for single and large Context Class.

>setContextProperty( const QString & name, QObject * value ) or ( const QString & name, const QVariant & value )
Create a Context Class, use it by the name.


Notify 

>non-NOTIFYable properties in QML 

http://stackoverflow.com/questions/6728615/warning-about-non-notifyable-properties-in-qml 

f the property values can change, then QML needs a notify signal so it can know when they have changed and update property bindings.

If they can't change, add CONSTANT to your property declaration, for example Q_PROPERTY(QString simplified READ simplified CONSTANT).

>signal 

Q_PROPERTY(bool IsLoggedIn READ GetIsLoggedIn WRITE SetIsLoggedIn NOTIFY loggedInChanged)

WRITE will do the signal connecting and tell UI to update.
Normally we don't need setter because we can also NOTIFY the UI (emit the signal) to update when the property is changed. 


>name rule

pattern for properties: <Prop>, Get<Prop>, Set<Prop>, <Prop>Changed (exception is Is* property where getter is same as property name).

---Binding End---


UISettings 

Position 

>anchors{}: generate usage

For performance reasons, you can only anchor an item to its siblings and direct parent.


Color 

>"transparent" 

used by some container:color: "transparent" 

>opacity

Opacity is specified as a number between 0 (fully transparent) and 1 (fully opaque). The default is 1.


Focus 

>ActiveFocus focus: true

>FocusScope Element


Send signal in QML

>C++

    QObject* item = pDeclarativeView->rootObject();

    if (item)

    {

        bool ret = connect(item, SIGNAL(linkClicked(QString)), this, SLOT(LinkActivated(QString)));

        Q_ASSERT(ret);

    }

>QML 

    signal linkClicked(string link)    

    onLinkActivated: mainView.linkClicked(link)s

Index 

>index


Component Element 

Components are reusable, encapsulated QML elements with well-defined interfaces


Image Element 

>source: qrc is not enough working for the image path, need add related direcrories like: Image/Sample.png


Text Element

>TextInput/TextEdit

-cursorDelegate, change the shape of the cursor between the text


Flickable Element 

>boundsBehavior


Binding Element 

>example

 Binding {

     target: contactName; property: 'text'

     value: name; when: list.ListView.isCurrentItem

 }

---UISettings End---


QMLDataModels

ListView Element(Flickable) 

Example:

http://qt-project.org/wiki/How_to_make_QML_ListView_align_bottom-to-top 

>listView

The main container

>delegate 

Set the Style, Layout

>mode
Set the data
        ListModel {
            id: messageListModel
            ListElement {
                Title: "<STRONG><FONT color=#0000cc>AutoCAD Exchange</FONT></STRONG>"            } 

            ListElement {
                Message: "Tom Jones invited 1 person to share <br><a href=\"TODO\">Floor_Plan.dwg </a>"            }
        }


>Model/View Programming

 

Signals from the model inform the view about changes to the data held by the data source.

Signals from the view provide information about the user's interaction with the items being displayed.

Signals from the delegate are used during editing to tell the model and view about the state of the editor.


>QModelIndex

The QModelIndex class is used to locate data in a data model. 

This class is used as an index into item models derived from QAbstractItemModel. QAbstractItemModel::createIndex() 


>Sample

        ListView {

            id: messageListView

            anchors {

                top: midView.top

                bottom: parent.bottom

                left: parent.left

                right: parent.right

            }


            model: notificationListModel  //data

            delegate: messageViewDelegate  //style

        }


---QMLDataModels End---

### QT_QML_GENERATE_QMLLS_INI 的作用 `QT_QML_GENERATE_QMLLS_INI` 是一个用于 Qt QML 插件开发的配置选项。它的主要功能是在构建过程中自动生成 `qmlls.ini` 文件,该文件描述了插件中的 QML 类型及其元数据[^4]。 当开发者创建了一个新的 QML 插件并希望将其集成到 Qt Creator 或其他工具中时,这个配置项可以简化流程。通过启用此选项,在构建项目的过程中会自动调用宏 `Q_IMPORT_QML_PLUGIN` 并生成必要的元数据文件,从而减少手动操作的需求[^2]。 以下是其具体的作用和使用方法: --- ### 配置方法 #### 1. **在 `.pro` 文件中设置** 为了使 `QT_QML_GENERATE_QMLLS_INI` 生效,需要在项目的 `.pro` 文件中添加如下内容: ```plaintext CONFIG += qt qml plugin QT_QML_GENERATE_QMLLS_INI = true ``` 这一步告诉构建系统需要为当前插件生成 `qmlls.ini` 文件,并确保所有依赖关系被正确解析[^4]。 #### 2. **编写 QML 插件代码** 假设已经按照标准方式实现了 QML 插件,则可以在 C++ 中注册这些类型以便它们能够被 QML 使用。例如: ```cpp #include <QQmlExtensionPlugin> #include <qqml.h> class MyPlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri) override { qmlRegisterType<MyCustomType>(uri, 1, 0, "MyCustomType"); } }; ``` 上述代码片段展示了如何定义一个新的 QML 扩展插件并将自定义类型注册给指定 URI[^5]。 #### 3. **验证生成结果** 完成以上步骤后运行 `qmake && make` 命令重新编译工程。如果一切正常的话,应该会在目标目录下看到新生成的 `qmlls.ini` 文件。它包含了关于已注册类型的详细信息,比如名称、版本号以及导入路径等[^6]。 --- ### 示例代码展示 下面是一个完整的例子来说明整个过程: #### 主程序入口 (`main.cpp`) ```cpp #include <QtWidgets> int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; QPushButton button("Load Plugin", &window); QObject::connect(&button, &QPushButton::clicked, [&]() { qDebug() << "Loading custom QML types..."; }); window.show(); return app.exec(); } ``` #### 插件实现部分 (`myplugin.cpp`) ```cpp #include <QQmlEngine> #include <QQmlContext> #include <QQmlComponent> void initializeMyModule(QQmlEngine *, QJSEngine *) {} qmlRegisterSingletonType<QObject>("com.example.mytypes", 1, 0, "MySingleton", [](QQmlEngine *, QJSEngine *) -> QObject* { static auto instance = new QObject(nullptr); return instance; }); ``` 注意这里我们还引入了单例模式的支持作为额外演示[^7]。 --- ### 总结 综上所述,`QT_QML_GENERATE_QMLLS_INI` 提供了一种便捷的方式来管理复杂项目中的 QML 插件资源声明工作流;不仅提高了效率而且减少了人为错误的可能性。对于初学者而言建议先熟悉基础概念再逐步深入学习高级特性如动态加载模块等功能[^8]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值