Completed example 3 with slots and properties

This commit is contained in:
Filippo Cucchetto 2015-01-05 13:55:41 +01:00
parent 0fb2f9992e
commit 50eeefa5c4
6 changed files with 168 additions and 7 deletions

View File

@ -1,5 +1,6 @@
:Authors:
Filippo Cucchetto <filippocucchetto@gmail.com>
Will Szumski <will@cowboycoders.org>
:Version: 0.1.0
:Date: 2015/01/02
@ -57,7 +58,7 @@ or by manually copying the library in your system lib directory
::
sudo cp build/dir/path/DOtherSide/libDOtherSide.so /usr/lib
First example: HelloWorld
Example 1: HelloWorld
----------
As usual lets start with an HelloWorld example.
Most of the NimQml projects are made by one or more nim and qml
@ -81,7 +82,7 @@ The following example shows the basic steps of each NimQml app
3. Call the ``exec`` proc of the QApplication instance for starting
the Qt event loop
Second example: exposing data to Qml
Example 2: exposing data to Qml
------------------------------------
The previous example shown you how to create a simple application
window and how to startup the Qt event loop.
@ -113,16 +114,82 @@ At the time of writing the QVariant class support the following types:
* bool
* QObject derived classes
Third example: exposing complex data and procedures to Qml
Example 3: exposing complex data and procedures to Qml
----------------------------------------------------------
As seen by the second example simple data is fine. However most
applications need to expose complex data, functions and
update the view when something change in the data layer.
This is achieved by creating object that derives from QObject.
This is achieved by creating an object that derives from QObject.
A QObject is made of :
1. ``Slots``: slots are function callable from the Qml engine
2. ``Signals``: signals allow the sending of events
1. ``Slots``: slots are function that could both be called from the qml engine and connected to Qt signals
2. ``Signals``: signals allow the sending of events and be connected to slots
3. ``Properties``: properties allows the passing of data to
the Qml view and make it aware of changes in the data layer
A QObject property is made of three things:
* a read slot, a method that return the current value of the property
* a write slot, a method that set the value of the property
* a notify signal for telling that the current value of the property has been changed
We'll start by looking at the main.nim file
``Examples/SlotsAndProperties/main.nim``
.. code-block:: nim
:file: ../Examples/SlotsAndProperties/main.nim
Here's nothing special happen except:
1. The creation of Contact object
2. The injection of the Contact object to the Qml root context
using the ``setContextProperty`` as seen in the previous
example
The Qml file is as follow:
``Examples/SlotsAndProperties/main.qml``
.. code-block:: qml
:file: ../Examples/SlotsAndProperties/main.qml
The qml is made by a Label, a TextInput and a button.
The label display the contact name and automatically udpates when
the concat name changes.
The button update the contact name with the TextInput text when clicked.
So where's the magic?
The magic is in the Contact.nim file
``Examples/SlotsAndProperties/Contact.nim``
.. code-block:: nim
:file: ../Examples/SlotsAndProperties/Contact.nim
What First we declare a QObject subclass and provide a simple
new method where:
1. invoke the ``create()`` procedure. This invoke the C++ bridge and allocate
a QObject instance
2. register a slot ``getName`` for reading the Contact name field
3. register a slot `` setName`` for writing the Contact name
4. register a signal ``nameChanged`` for notify the contact name changes
5. register a property called ``name`` of type ``QString`` with the given
read, write slots and notify signal
The two slots method implementation are trivial and consist in standard
nim methods. However ``setName`` slot method shows how to emit a signal
by using the ``emit`` method.
The last thing to condider is the override of the ``onSlotCalled`` method.
This method is called by the NimQml library when an invokation occur from
the Qml side for one of the QObject slot.
The usual implementation for the onSlotCalled method consists in a
switch statement that forward the arguments to the correct slot.
If the invoked slot has a return value this is always in the index position
0 of the args array.
Example 4: QtObject macro

View File

@ -1,3 +1,4 @@
add_subdirectory(HelloWorld)
add_subdirectory(SimpleData)
add_subdirectory(Simple)
add_subdirectory(SlotsAndProperties)

View File

@ -0,0 +1,2 @@
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
add_nim_executable(TARGET SlotsAndProperties SOURCES main.nim PATHS ../../NimQml)

View File

@ -0,0 +1,31 @@
import NimQml
type Contact = ref object of QObject
m_name: string
template newContact*(): Contact =
var result = Contact(m_name: "initialName")
result.create()
result.m_name = "InitialName"
result.registerSlot("getName", [QMetaType.QString])
result.registerSlot("setName", [QMetaType.Void, QMetaType.QString])
result.registerSignal("nameChanged", [QMetaType.Void])
result.registerProperty("name", QMetaType.QString, "getName", "setName", "nameChanged")
result
method getName*(self: Contact): string =
result = self.m_name
method setName*(self: Contact, name: string) =
if self.m_name != name:
self.m_name = name
self.emit("nameChanged")
method onSlotCalled(self: Contact, slotName: string, args: openarray[QVariant]) =
case slotName:
of "getName":
args[0].stringVal = self.getName()
of "setName":
self.setName(args[1].stringVal)
else:
discard()

View File

@ -0,0 +1,27 @@
import NimQml
import Contact
proc mainProc() =
var app: QApplication
app.create()
defer: app.delete()
var contact = newContact()
defer: contact.delete()
var engine: QQmlApplicationEngine
engine.create()
defer: engine.delete()
var variant: QVariant
variant.create(contact)
defer: variant.delete()
var rootContext: QQmlContext = engine.rootContext()
rootContext.setContextProperty("contact", variant)
engine.load("main.qml")
app.exec()
when isMainModule:
mainProc()

View File

@ -0,0 +1,33 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.1
ApplicationWindow
{
width: 400
height: 300
Component.onCompleted: visible = true
ColumnLayout
{
anchors.fill: parent
Label
{
text: "Current name is:" + contact.name
}
TextField
{
id: textField
}
Button
{
text: "Change Name"
onClicked: contact.name = textField.text
}
}
}