Q_PROPERTY

I'm confused about Q_PROPERTY

can any body tell what "Q_PROPERTY (QString text text READ WRITE setText NOTIFY textChanged)" means

Hello

Q_PROPERTY is a macro and a part of the system of Qt properties. Its purpose is to allow us to bind the properties that we use in our QML to C++ data by appropriate methods. Your example combines three things a QML property whose id is "text". Let's review each of them:

Text READ: it means "to get a value for the text property, call a C++ method text()".

WRITE setText: in other words, "if we change the value of the text property to QML by assigning a value, communicate to C++ by calling a method, setText (QString NewText).

TextChanged NOTIFY: This means that "If the value of the data in my C++ object is modified by a non - QML action, notify me that it has changed so that I can update the value of the property in QML by transmitting the signal of Qt, whose name is «textChanged()»»

There is still information on the QML and C++ integration in our documentation here:

http://developer.BlackBerry.com/native/documentation/Cascades/dev/integrating_cpp_qml/

Here is an example of my own as well:

Q_OBJECT

    // a Q_PROPERTY declaration is a binding between a property we can use in QML and underlying C++ methods and signals

Q_PROPERTY(
        // the name of our property as used from QML
        QString my_property
        // a method that will be called to populate our QML property with a value from C++
        READ getMyProperty
        // a method that will be called when we want to change the value of our corresponding C++ variable
        WRITE setMyProperty
        // a signal that will be emitted if the underlying data value changes. This signal will be automatically connected to our QML property
        // so that anywhere our property has been used, it's value will be updated
        NOTIFY signalMyPropertyChanged)

Figure 1 declaring a Q_PROPERTY

And then we declare signals and the associated methods:

public:

    // for my Q_PROPERTY
    QString getMyProperty();
    void setMyProperty(QString text);

    Q_INVOKABLE void resetMyProperty();

signals:
    // signal that is emitted if my property value changes
    void signalMyPropertyChanged();

Figure 2: declare the methods and signals used by the Q_PROPERTY

private:
    QString _some_text;

Figure 3: Our C++ data we bind to our property

Note that I also used Q_INVOKABLE authorizing the call directly from the resetMyProperty() to the specified method of QML.

QString ApplicationUI::getMyProperty() {
    qDebug() << "XXXX getMyProperty called";
    return _some_text;
}

void ApplicationUI::setMyProperty(QString some_text) {
    qDebug() << "XXXX setMyProperty called:" << some_text;
    _some_text = some_text;
    qDebug() << "XXXX setMyProperty emiting signalMyPropertyChanged";
    emit signalMyPropertyChanged();
}

void ApplicationUI::resetMyProperty() {
    qDebug() << "XXXX resetMyProperty called";
    setMyProperty("Hello I am a property");
}

Figure 4: implementation of C++ functions

    QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);

    // expose the property to QML
    qml->setContextProperty("my_prop", this);

Figure 5 expose our C++ object to QML

import bb.cascades 1.2

Page {
    Container {

        TextField {
            id: tf
            objectName: "tf"
            // this causes the READ method bound to our property to be called
            text: my_prop.my_property
        }
        Button {
            text: "Change Property"
            onClicked: {
                // this causes the WRITE method bound to our property to be called
                my_prop.my_property = tf.text
            }
        }
        Button {
            text: "Reset"
            onClicked: {
                // this calls a C++ method that was exposed using Q_INVOKABLE
                my_prop.resetMyProperty();
            }
        }
    }
}

Figure 6 the QML

When I run my application, I see that TextField tf is generated automatically and this is accomplished by the system calling the getMyProperty READING method. So, if I change the text and click the button of change of ownership, I see that the WRITE method is called. If I click on Reset, the Q_INVOKABLE method is called directly from QML and it my signal, so notify the QML bound property value has changed. This causes a call to the READ method and my text field in QML is updated.

XXXX getMyProperty called
XXXX setMyProperty called: "Hello"
XXXX setMyProperty emiting signalMyPropertyChanged
XXXX getMyProperty called
XXXX resetMyProperty called
XXXX setMyProperty called: "Hello I am a property"
XXXX setMyProperty emiting signalMyPropertyChanged
XXXX getMyProperty called

Figure 7: out of the call display console

Hope that helps

Martin

Tags: BlackBerry Developers

Similar Questions

  • Expose the QGeoAddress with Q_PROPERTY object to QML

    Hello

    I have a class that I wrote which gets the location of the device and does a reverse search for Geolocation. In my C++, I have an QGeoAddress object, but when I try and access its attributes of QML, I get a "property: unknown type: address QGeoAddress ' error."

    I'm loading my class, called LocationInformation in QML by using attachedObects:

    attachedObjects: [
            LocationInformation {
                id: locationInformation
            }
        ]
    

    In my head of class LocationInformation, I set the latitude and longitude as attributes such as address:

    class LocationInformation : public QObject
    {
        Q_OBJECT
    
        Q_PROPERTY(double latitude READ latitude)
        Q_PROPERTY(double longitude READ longitude)
        Q_PROPERTY(QGeoAddress address READ getAddress)
    
        ...
    }
    

    I am able to call locationInformation.latitude and get a value, but this isn't the case for the address. I have to perform an extra step in order to obtain an QGeoAddress object to be recognized by QML?

    Thank you

    javabb

    QGeoAddress inherit from QObject, my code snippet above will not work (and is what this error means ).  To expose to QML, you would have to wrap up in your own C++ class that extends from QObject.  Or just use c++ instead of QML.

  • GroupDataModel as Q_PROPERTY

    Hello

    Maybe, I am interested in this the wrong way, but is it possible to have a GroupDataModel like a Q_PROPERTY? I want to be able to update the data model via a WebService in C++ with JSON analysis, etc. - and then use the property of NOTIFICATION of it to react in QML. I did it successfully with other types of data, but with GroupDataModel, even though I have

    #include - I am just completely unable to see GroupDataModel as an object type in the header files. I just get "GroupDataModel does not name a type" etc. There may be something that I am missing.

    If anyone else has tried this? Thank you!

    Oh, my apologies - all the time I forgot to add this to the top of my header file:

    using namespace bb::cascades;

  • Expose the abstract as Q_PROPERTY to QML type

    Hello

    I defined a base class to implement interface:

    class AbstractImageProcessor : public QObject
    {
    public:
        AbstractImageProcessor(QObject * parent) : QObject(parent) {}
        virtual QImage process(const QByteArray &data) = 0;
        virtual ~AbstractImageProcessor(){ }
    };
    

    Such implementation that I want from QML looks like this:

    class WebImageProcessor : public AbstractImageProcessor
    {
        Q_OBJECT
        Q_PROPERTY(int maxHeight READ getMaxHeight WRITE setMaxHeight NOTIFY maxHeightChanged)
        Q_PROPERTY(int maxWidth READ getMaxWidth WRITE setMaxWidth NOTIFY maxWidthChanged)
        Q_PROPERTY(bool fit READ isFit NOTIFY fitChanged)
        public WebImageProcessor(QObject * parent = 0) : AbstractImageProcessor(parent) {}
        virtual ~WebImageProcessor() {}
        /* rest of code omitted */
    };
    

    I want to expose this AbstractImageProcessor as one property on another type QML:

    class WebImageView : public bb::cascades::ImageView {
        Q_OBJECT
        Q_PROPERTY(AbstractImageProcessor* processor READ getProcessor WRITE setProcessor NOTIFY processorChanged)
        WebImageView(bb::cascades::Container * parent) : bb::cascades::ImageView(parent)  {}
        virtual WebImageView() {}
        /* rest of code omitted */
    };
    

    So I save my custom with QML types

    //application.cpp
    qmlRegisterUncreatableType("foo.controls", 1, 0, "AbstractImageProcessor", ""); qmlRegisterType("foo.controls", 1, 0, "WebImageProcessor");
    qmlRegisterType("foo.controls", 1, 0, "WebImageView");
    

    How I want to use it in QML

    //main.qml
    import foo.controls 1.0
    /* omitted containers */
    
    WebImageView {
      processor: WebImageProcessor {
         maxHeight: 500
         maxWidth: 300
      }
      /* rest of properties omitted */
    }
    

    But once I launch my request, that he fails to analyze the document qml.

    BB::Cascades:QmlDocument: error loading QML of: QUrl ("asset:///main.qml")
    -errors: (asset:///main.qml:138:57: impossible to assign to the property object) bb::cascades:QmlDocument:createRootObject document is not loaded or has errors, cannot create the root

    In fact, if I hover over the WebImageProcessor class in the editor, he says:

    The super type of the WebImageProcessor component is unknown, some of its properties are not validated.

    Now, the thing is that the example cascades built in ListView exposes a type abstract as a Q_PROPERTY:

    http://developer.BlackBerry.com/native/reference/Cascades/bb_cascades_listview.html#property-datamod...

    Event inspect bb::cascades and bb::cascades:ListView header files:ataModel gives me no other indices because he did essentially the same way.

    I save the types in a different way? If so, how?

    If I use WebImageProcessor in the Q_PROPERTY instead of the AbstractImageProcessor then it works as expected, but I want to expose the abstract type, and as waterfalls is a then it is certainly possible somehow

    Turns out that I've been away an inside AbstractImageProcessor Q_OBJECT macro.

    I swear that I got before with no luck. Perhaps the project today solved the problem of cleaning.

    In any case, it works the way I wanted, with the only exception that Momentics complains about the assignment in qml, but this is just a minor inconvenience.

  • BlackBerry Q10 timer does not work for a project of 10 Q Lable in Blackberry

    Hi all

    I'm just a new Black Berry Q 10 and just beginner. I get some helpful solutions here to correct my mistakes. I am very grateful for this site and its members.

    In my application, I would like to add a timer to a lable. for every second, I want to Christophe Lable value. Here is my code Qml and timer.

    // Default empty project template
    import bb.cascades 1.0
    import CustomTimer 1.0
    // creates one page with a label
    Page {
        Container {
            id:root
            layout: DockLayout {}
            property int f: 10
            Label {
                id: timerLabel
                text: qsTr("Hello World")
                textStyle.base: SystemDefaults.TextStyles.BigText
                verticalAlignment: VerticalAlignment.Center
                horizontalAlignment: HorizontalAlignment.Center
    
            }
            Timer {
                id: lightTimer
                // Specify a timeout interval of 1 second
                interval: 1000
                onTimeout: {
                    root.f -= 1;
                    timerLabel.text = "Timer:"+root.f;
                    lightTimer.start();
                    if(root.f<0){
                        lightTimer.stop();
                    }
                    } // end of onTimeout signal handler
            } // end of Timer
    
        }
    }
    
    #include 
    #include "timer.hpp"
    
    Timer::Timer(QObject* parent)
         : bb::cascades::CustomControl(),
         _timer(new QTimer(this))
    {
        Q_UNUSED(parent);
        connect(_timer, SIGNAL(timeout()), this, SIGNAL(timeout()));
        setVisible(false);
    }
    
    bool Timer::isActive()
    {
        return _timer->isActive();
    }
    
    int Timer::interval()
    {
        return _timer->interval();
    }
    
    void Timer::setInterval(int m_sec)
    {
        // If the timer already has the specified interval, do nothing
        if (_timer->interval() == m_sec)
            return;
    
        // Otherwise, set the interval of the timer and emit the
        // intervalChanged() signal
        _timer->setInterval(m_sec);
        emit intervalChanged();
    }
    
    void Timer::start()
    {
        // If the timer has already been started, do nothing
        if (_timer->isActive())
            return;
    
        // Otherwise, start the timer and emit the activeChanged()
        // signal
        _timer->start();
        emit activeChanged();
    }
    
    void Timer::stop()
    {
        // If the timer has already been stopped, do nothing
        if (!_timer->isActive())
            return;
    
        // Otherwise, stop the timer and emit the activeChanged()
        // signal
        _timer->stop();
        emit activeChanged();
    }
    
    #ifndef TIMER_HPP_
    #define TIMER_HPP_
    
    #include 
    #include 
    
    class QTimer;
    
    class Timer : public bb::cascades::CustomControl
    {
        Q_OBJECT
    
        Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
        Q_PROPERTY(int interval READ interval WRITE setInterval
                   NOTIFY intervalChanged)
    
    public:
        explicit Timer(QObject* parent = 0);
    
        bool isActive();
        void setInterval(int m_sec);
        int interval();
    
    public
    
    slots:
        void start();
        void stop();
    
    signals:
        void timeout();
        void intervalChanged();
        void activeChanged();
    
    private:
        QTimer* _timer;
    };
    
    #endif /* TIMER_HPP_ */
    

    and I sign up time as follws custome...

    Registering the custome timer
    qmlRegisterType("CustomTimer", 1, 0, "Timer");
        // create scene document from main.qml asset
        // set parent to created document to ensure it exists for the whole application lifetime
        QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
    

    where I'm wrong... I'm just Hello world but Timer shows no lable value. Please help me!

    Hello

    It was my mistake in looking at timer in Qml. The good way to start is given below.

    Already... .i was

      Timer {
                id: lightTimer
                // Specify a timeout interval of 1 second
                interval: 1000
                onTimeout: {
                    root.f -= 1;
                    timerLabel.text = "Timer:"+root.f;
                    lightTimer.start();
                    if(root.f<0){
                        lightTimer.stop();
                    }
                   } // end of onTimeout signal handler
            } // end of Timer
    

    but now to hide a bad start timer and start in the right way

    Timer {
                id: lightTimer
                // Specify a timeout interval of 1 second
                interval: 1000
                onTimeout: {
                    root.f -= 1;
                    timerLabel.text = "Timer:"+root.f;
    //                lightTimer.start();
    //                if(root.f<0){
    //                    lightTimer.stop();
    //                }
                   } // end of onTimeout signal handler
            } // end of Timer
    
        }
        onCreationCompleted: {
            lightTimer.start();
        }
    

    Thank you!!!

  • How to register QGeoCoordinate fo QML

    Hello

    is it possible to use QGeoCoordinate as type for Q_PROPERTY?

    don't have to work - QML allways tells me that it is an unknown type

    I can't save as type

    qmlRegisterType(...)

    does not compile

    registration as a Metatype does not help:

    qRegisterMetaType("QGeoCoordinate");

    any ideas?

    GOD wrote:

    Just an idea:

    write a wrapper of QObject with QGeoCoordinate inside und class using Q_PROPERTY to access

    made for QGeoCoordinate and QGeoAddress

    works perfectly

    will be published soon Open Source as part of my DSL QObject to generate C + c++ / code Qt to a domain model.

    a class looks like this:

      dto CustomerData {
            var QString uuid;
            domainKey int id;
            var QString companyName;
            var GeoCoordinate coordinate;
            var GeoAddress geoAddress;
        }
    

    DSL based Xtext / Xtend of Eclipse.

    All code boring card Q_PROPERTY, getter/setter/signals, creating the class of a JSON or persistent lazy or built-in classes, JSON, QDeclarativeList, references GroupDataModel support... will be generated automatically.

    Then, it will be easy to deal with QObject * between C++ and QML.

  • QML signal handling Q fast

    Hey. If I have this line in a class that is exposed to QML (other things are working ok so I think that I exposed the class C++ OK)

            Q_PROPERTY(int downloadedDataSinceStart READ downloadedData NOTIFY downloadChanged)
    

    What is the line of javascript look like process the signal of downloadChanged? I tried

    _myClass.onDownloadChanged:  {
    
         /// do this
    
    }
    

    but nothing happened. SEO _myClass.downloadedDataSinceStart has worked, but not my on... slot code.

    What should the qml file javascript look like pls?

    See you soon

    J

    It might be what you want to do is the following:

    _myClass.downloadChanged.connect(myJavaScriptSignalHandler);
    
    :
    :
    :
    
    function myJavaScriptSignalHandler() {
    // Code ...
    }
    

    See this reference:

    http://doc.Qt.IO/Qt-4.8/qmlevents.html

  • Strange behavior of ListView

    Hello
    I use following code:

     ListView {       id: listView listItemComponents: ListItemComponent {           Container {               id: listItemContainer               property string packageId: ListItemData.packageId               property variant packageDetailsPage               layout: AbsoluteLayout { }               WebImageView               {                   preferredHeight: 290                   preferredWidth: 751                   url: ListItemData.url;              }          }     }
    

    code for WebImageView:

    webimageview. HPP

    #ifndef WEBIMAGEVIEW_H_
    #define WEBIMAGEVIEW_H_
    
    #include 
    #include 
    #include 
    #include 
    using namespace bb::cascades;
    
    class WebImageView: public bb::cascades::ImageView {
        Q_OBJECT
        Q_PROPERTY (QUrl url READ url WRITE setUrl NOTIFY urlChanged)
        Q_PROPERTY (float loading READ loading NOTIFY loadingChanged)
    
    public:
        WebImageView();
        const QUrl& url() const;
        double loading() const;
    
        public Q_SLOTS:
        void setUrl(const QUrl& url);
        void clearCache();
    
        private Q_SLOTS:
        void imageLoaded();
        void dowloadProgressed(qint64,qint64);
    
        signals:
        void urlChanged();
        void loadingChanged();
    
    private:
        static QNetworkAccessManager * mNetManager;
        static QNetworkDiskCache * mNetworkDiskCache;
        QUrl mUrl;
        float mLoading;
    
        bool isARedirectedUrl(QNetworkReply *reply);
        void setURLToRedirectedUrl(QNetworkReply *reply);
    };
    
    #endif /* WEBIMAGEVIEW_H_ */
    

    webimageview.cpp

    #include "WebImageView.h"
    #include 
    #include 
    //#include 
    #include 
    
    using namespace bb::cascades;
    
    QNetworkAccessManager * WebImageView::mNetManager = new QNetworkAccessManager();
    //QNetworkDiskCache * WebImageView::mNetworkDiskCache = new QNetworkDiskCache();
    
    WebImageView::WebImageView() {
        // Initialize network cache
        //mNetworkDiskCache->setCacheDirectory(QDesktopServices::storageLocation(QDesktopServices::CacheLocation));
    
        // Set cache in manager
        //mNetManager->setCache(mNetworkDiskCache);
    
        // Set defaults
    
        mLoading = 0;
    }
    
    const QUrl& WebImageView::url() const {
        return mUrl;
    }
    
    void WebImageView::setUrl(const QUrl& url) {
        // Variables
    
            mUrl = url;
            mLoading = 0;
            qDebug()<<"url:: "<get(request);
    
            // Connect to signals
            QObject::connect(reply, SIGNAL(finished()), this, SLOT(imageLoaded()));
            QObject::connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(dowloadProgressed(qint64,qint64)));
    
            emit urlChanged();
    
    }
    
    double WebImageView::loading() const {
        return mLoading;
    }
    
    void WebImageView::imageLoaded() {
        // Get reply
        QNetworkReply * reply = qobject_cast(sender());
        QObject::disconnect(reply, SIGNAL(finished()), this, SLOT(imageLoaded()));
        QObject::disconnect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(dowloadProgressed(qint64,qint64)));
        if (reply->error() == QNetworkReply::NoError) {
            if (isARedirectedUrl(reply)) {
                setURLToRedirectedUrl(reply);
                return;
            } else {
                QByteArray imageData = reply->readAll();
                setImage(Image(imageData));
            }
        }
        // Memory management
        reply->deleteLater();
    }
    
    bool WebImageView::isARedirectedUrl(QNetworkReply *reply) {
        QUrl redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
        return !redirection.isEmpty();
    }
    
    void WebImageView::setURLToRedirectedUrl(QNetworkReply *reply) {
        QUrl redirectionUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
        QUrl baseUrl = reply->url();
        QUrl resolvedUrl = baseUrl.resolved(redirectionUrl);
    
        setUrl(resolvedUrl.toString());
    }
    
    void WebImageView::clearCache() {
        //mNetworkDiskCache->clear();
    }
    
    void WebImageView::dowloadProgressed(qint64 bytes, qint64 total) {
        mLoading = double(bytes) / double(total);
    
        emit loadingChanged();
    }
    

    I use ListDataModel. and code above works fine and the loading of the images. But when there are more than 100 items in a list it shows the bad images in some WebImageView. When you scroll through random images change. I checked the url property of webImageView to the point where bad image is loaded, but there the right url.

    in this connection, blackberry says that view list follows MVC architecture, and QObject belonged to ListView objects are deleted when scrolling out of the area visible to the element to which they belong, or when the ListView itself is deleted. What is the cause of my problem? If not, this what's wrong with this code? Help, please...

    nik005 wrote:

    @ekke Yes. If I scroll slowly, it works fine.

    THX.

    Then, it's the same reason.

    as soon as I have a small reproducible application to create a problem, I'll add this thread and let you know

  • Convert a Contact to a QVariant in a list

    Hey. Since I'm still pretty new to c ++ my understanding of the collocation of type is incomplete. I need to get my Contacts QList into a QVariantList, so I can put it in the constructor of a QListDataModel for use in a ListView. I can't get my Contact to convert a QVariant. Here's the code. I also tried to convert a Contact or a Contact * in a QVariant without success.

    Enjoy your time,

    See you soon
    Justin D.

    Q_DECLARE_METATYPE(Contact);
    Q_DECLARE_METATYPE(std::list);
    
    ///////////////////////////////////////////////////
    
        if (partial.length() < 3)
            return;
    
        QString completed = partial;
    
        ContactAutoCompleteSearchFilters cacsf;
        cacsf.setLimit(5);
        cacsf = cacsf.setIncludePhotos(true);
        cacsf = cacsf.setSearchField(SearchAutoCompleteField::Email);
        cacsf = cacsf.setSearchValue(partial);
    
        ContactService cs;
    
        qRegisterMetaType("Contact");
    
        QList ql = cs.searchContactsAutoComplete(cacsf);
        std::list l = ql.toStdList();
        QVariantList qvl = QVariantList::fromStdList(l);   /// <<<<< Error, No matching function for call
    

    QVariant supports a limited set of objects. But one of them is QObject *, which allows to use
    qVariantFromValue(objectPointer)

    Now the second question would be if the implementation of Contact can be used in QML (saved successfully). I have not tried, but if it does not, you will need to write your own wrapper class that returns the properties that you need, for example using Q_PROPERTY.

  • Box problems

    I have problems to call the function c ++ for the
    OnCheckedchanged {}
    Whenever I call a function,
    Example: _app.sum (...)
    the console says: could not find the application variable

    But I am able to use the same function in buttons with {onClicked}
    Sum function is defined as ApplicationUI::sum (QString) voi...

    Oh! Lol, I just responded to someone on WhatsApp who asked the exact same question, I would copy and paste of my response.

    You should treat your listItem, as if she lives in a different world and all they know is their parent (ListView). So, if you want to use the Q_PROPERTY foo in bar class that you have setContextProperty() with the name _bar, you can't use _bar.foo
    Instead, create a property in your ListView that point to it, like this:
    property variant foo: _bar.foo

    And in your listItem, use this:
    Title: mainItemName.ListItem.view.foo

    (mainItemName is the ID that you will give to your content in your ListItemComponent, it's usually a StandardListItem or a container)

    You can see an example in this code:
    https://github.com/RodgerLeblanc/tutorial/BLOB/master/assets/tutorial/TutorialSheet.QML

  • Another Question for C++ question QML class

    Hello

    I have a class that I joined in QML. I have a couple of Q_PROPERTY int and QString. Now I would like to spend a lot of information to the QML which includes data elements. I would spend the entire data group from the C++ QML and then have easy access to data elements.

    I was wondering what the best structure to allow that load the structure in C++ and access the items in the QML.

    Thanks in advance.

    Just thought that I would finalize the solution that worked and marks it as such.

    all

    class PData::PData(QObject* parent) {
    
      Q_PROPERTY(QVariantList pData READ pData NOTIFY pDataChanged)
    public:
      QVariantList pData();
    
    signals:
      void pDataChanged();
    private:
      QVariantList m_pData;
    

    .cpp

    QVariantList PClass:pData()
    {
      return m_pData;
    }
    void function() {
      QVariantMap tMap;
      tMap["t1"] = 1;  tMap["t2"] = 2;
      m_pData.append(tMap);  emit pDataChanged();}
    

    . QML

    onPDataChanged: {
      var pItem = myPData.pData;  var dataMap = pitem[0];  var t1 = dataMap["t1"];  var t2 = dataMap["t2"];
    }
    
    attachedObjects: [  PData {    id: myPData  }]
    

    Thanks to all who helped.

  • Loading an image works on Z10, but not on the Q5

    I use FilePicker to load an image from the library by using the following code

    Container {
            ...
    
            ImageView {
                id: imgView
                verticalAlignment: VerticalAlignment.Center
                horizontalAlignment: HorizontalAlignment.Center
                scalingMethod: ScalingMethod.AspectFit
                maxHeight: 250
                minHeight: 100
                bottomMargin: 30.0
    
            }
    
        }
        Container {
            verticalAlignment: VerticalAlignment.Bottom
            horizontalAlignment: HorizontalAlignment.Fill
            bottomPadding: 30.0
            leftPadding: 30
            rightPadding: 30
    
            Button {
                id: btnSelectImg
                topPadding: 25
                horizontalAlignment: HorizontalAlignment.Fill
                text: qsTr("Select Image") + Retranslate.onLocaleOrLanguageChanged
                onClicked: {
                    console.log("FilePicker")
                    picker.open()
                }
    
                attachedObjects: [
                    FilePicker { //image picker
                        id: picker
                        property string selectedFile
                        type: FileType.Picture
                        title: qsTr("Select Image") + Retranslate.onLocaleOrLanguageChanged
                        onFileSelected: {
                            imgView.imageSource = "file://" + selectedFiles[0];
                        }
    
                    }
                ]
            }
        }
    }
    

    Copy the following code to display the image correctly on Z10, but not on Q5 however both running the same version.

    No idea what could be the problem?

    It turns out that the problem is exactly as described by dbigham, ImageView can handle images up to a certain size depedning on the device.

    I added a C++ code to resize the image before feeding it to QML

    QML code:

    ImageView {
                id: imgView
                attachedObjects: [
                    ImageTracker {
                        id: imgViewTracker
    
                        onStateChanged: {
                            if (state == ResourceState.Loaded)
                            {
                                imgView.image = imgViewTracker.image
                                console.log("Shared image loaded correctly!")
                            }
                            else if (state == ResourceState.ErrorMemory)
                            {
                                console.log("Shared image load: Error Memory!")
                            }
                            else if (state == ResourceState.ErrorInvalidFormat || state == ResourceState.ErrorNotFound) {
                                console.log("Shared image load: " + state + "!")
                            }
                        }
                    },
                    FilePicker { //image picker
                        id: picker
                        property string selectedFile
                        type: FileType.Picture
                        title: qsTr("Select Image") + Retranslate.onLocaleOrLanguageChanged
                        onFileSelected: {
                            _app.loadImage(selectedFiles[0],300,200)
                            imgViewTracker.image = _app.image;
                        }
    
                    }
                ]
    
            }
    

    C++ code:

    void ApplicationUI::loadImage(QString strImageFileName, int width, int height)
     {
         QImage image;
    
         image.load(strImageFileName);
    
         image = image.scaled(width, height, Qt::KeepAspectRatioByExpanding);
    
         QImage swappedImage = image.rgbSwapped();
         if(swappedImage.format() != QImage::Format_RGB32) {
             swappedImage = swappedImage.convertToFormat(QImage::Format_RGB32);
         }
         const bb::ImageData imageData = bb::ImageData::fromPixels(swappedImage.bits(), bb::PixelFormat::RGBX, swappedImage.width(), swappedImage.height(), swappedImage.bytesPerLine());
    
         m_image = bb::cascades::Image(imageData);
         emit imageChanged();
     }
    
    QVariant ApplicationUI::image() const
     {
         return QVariant::fromValue(m_image);
     }
    

    C++ header:

    class ApplicationUI : public QObject
    {
    ...
    
    Q_PROPERTY(QVariant image READ image NOTIFY imageChanged)
    
    public:
    ...
    
    Q_INVOKABLE void loadImage(QString strImageFileName, int width, int height);
    
    signals:
    ...
    
    void imageChanged();
    
    private:
    ...
        QVariant image() const;
        bb::cascades::Image m_image;
    
  • class.h file not recognized by the compiler signals section

    Hey. My class .h file is pasted below with a screenshot. The signals keyword is cyan, when I think it should be purple. Also when I mouse over the word he said Macro Expansion (protected) (even though the words of Macro are green).

    I don't think that the compiler is grateful signals: article because the signal that he is apparently not defined.

    Appreciate any help,

    Justin.

    /*
     * Count.h
     *
     *  Created on: 23/03/2015
     *      Author: Justin
     */
    
    #ifndef COUNT_H_
    #define COUNT_H_
    
    #include 
    
        class Count : public QObject
        {
            Q_OBJECT
            Q_PROPERTY(int downloadedDataSinceStart READ downloadedData WRITE setDownloadedData NOTIFY downloadChanged)
    
        public:
            Count(QObject* parent = 0);
            virtual ~Count();
    
            int downloadedData();
            void setDownloadedData(int data);
    
        signals:
    
            void downloadChanged();
    
        private:
    
            int m_data; // The data downloaded in Mb
    
        };
    
    #endif /* COUNT_H_ */
    

    Screenshot:

    downloadChanged() is a signal and should not be reported as a RPC function, which means that you must delete these lines (sorry for the formatting):
    {} void County: downloadChange()
    //...
    }

    If you want to run code when the downloadChange() signal is displayed, you must connect a machine slot to this signal, run the code in the slot (ie: onDownloadChanged())

    See here for more info about the signals and slots:
    http://developer.BlackBerry.com/native/documentation/Cascades/dev/signals_slots/

  • c ++ bool qml undefined when exposedwith ContextProperty

    In an attempt to circumvent the problem of PickerItemComponent not been able to access what anyone outside himself, I exposed a bool for QML (my application has a Bool QML, called compactMode, long story), now since I can't access that bool compactMode I tried to expose a c ++ one like this:

    public:
    
        bool compactModeGlobal;
    
        QDeclarativeEngine *engine = QmlDocument::defaultDeclarativeEngine();
        QDeclarativeContext *rootContext = engine->rootContext();
    
        rootContext->setContextProperty("compactModeGlobal", compactModeGlobal);
    

    It gives me the warning of "Member"compactModeGlobal"has not been initialized in the constructor.

    That, of course, it won't let me spend this compactModeGlobal bool QML

    I missed something important it?

    In general in the ApplicationUI constructor, you would report the properties that you want to expose from C++, using Q_PROPERTY and QObject ceremony associated with the functions of getter/setter/broadcasting signal and set a context property on your document main qml like this:

    QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
    qml->setContextProperty("_app", this);
    

    where "this" in the call of setContextProperty() refers to the ApplicationUI object.

    Edit: So, in your doc QML, you acceding C++ properties using:

    SomeQMLComponent {
        someQMLProperty:  _app.someCppProperty
    }
    
  • Native of filebrowse using and the cascading Save dialog box

    In my application I need to open file and file save dialog box when a specific button is clicked. I looked at the docs of stunts, but I found that the native options. Tried the native alert dialog, change of filebrowse dialog type. It displays well on Simulator, but could not get any output file that will be used in the Qt code.

    I pass these parameters

    int * num = NULL;

    char * folder [1024];
    dialog_update (alert_dialog);

    to dialog_event_get_filebrowse_filepaths(event,file,num), but it always returns BPS_FAILURE.

    In addition, access_shared is present in the bar-descriptor

    Here is my code:

    //slot function
    void App::fileOpen(){
        //===========================
            dialog_instance_t alert_dialog = 0;
    
            bps_initialize();
    
            dialog_request_events(0);    //0 indicates that all events are requested
    
            if (dialog_create_filebrowse(&alert_dialog) != BPS_SUCCESS) {
                        fprintf(stderr, "Failed to create alert dialog.");
                        return ;
                }
                const char* extensions[] = {"*.*","*.jpg","*.jpeg","*.mp3","*.wav","*.mp4","*.txt","*.doc","*.pdf"};
                int items = 9;
                if(dialog_set_filebrowse_filter(alert_dialog, extensions,items) != BPS_SUCCESS){
                    fprintf(stderr, "Failed to set alert dialog message text.");
                            dialog_destroy(alert_dialog);
                           alert_dialog = 0;
                           return ;
                }
               if( dialog_set_filebrowse_multiselect(alert_dialog,FALSE)!=BPS_SUCCESS){
                   fprintf(stderr, "Failed to set alert dialog message text.");
                                dialog_destroy(alert_dialog);
                               alert_dialog = 0;
                               return ;
               }
    
            if (dialog_show(alert_dialog) != BPS_SUCCESS) {
                fprintf(stderr, "Failed to show alert dialog.");
                dialog_destroy(alert_dialog);
                alert_dialog = 0;
                return ;
            }
    
            int shutdown =0;
            while (!shutdown) {
                bps_event_t *event = NULL;
                bps_get_event(&event, -1);    // -1 means that the function waits
                                              // for an event before returning
    
                if (event) {
                    if (bps_event_get_domain(event) == dialog_get_domain()) {
    
                        int selectedIndex =
                            dialog_event_get_selected_index(event);
                        const char* label =
                            dialog_event_get_selected_label(event);
                        const char* context =
                            dialog_event_get_selected_context(event);
    
                        char **fileArray[]={};
                        int *numFiles = NULL;
                       //
                              if(selectedIndex == 0){
           shutdown = 1;//user press the cancel button on dialog; close the dialog
       }
       else if(selectedIndex == 1){
           if(dialog_event_get_filebrowse_filepaths(event,file,num)!=BPS_SUCCESS){
           fprintf(stderr,"File open fail");
       }
       else{
    
    //debug purposes
           fprintf(stderr,"File array: %d/n",sizeof(file)*1024);
               fprintf(stderr,"Num files: %n",num);
               //fprintf(stderr,"Files int: %d",files);
       }
    
       }
                    }
                }
            }
    
            if (alert_dialog) {
                dialog_destroy(alert_dialog);
            }
            //===========================
    }
    

    Native Subforums have no useful information on this subject. Any help is greatly appreciated

    Hello again, here's the example as promised.

    To use the native filebrowse dialog box, the native code must run in its own thread to prevent the user interface in the Cascades to block. This is achieved by encapsulating all the dialog box code in a class derived from QThread.  The class I wrote is called FileBrowseDialog

    FileBrowseDialog.hpp

    #ifndef FILEBROWSEDIALOG_HPP_
    #define FILEBROWSEDIALOG_HPP_
    
    #include 
    #include 
    #include 
    
    /*
     * The file browse dialog displays a dialog to browse and select
     * files from shared folders on the system.
     */
    class FileBrowseDialog : public QThread
    {
        Q_OBJECT
    
        /*
         * QML property to allow multiple selection
         */
        Q_PROPERTY(bool multiselect READ getMultiSelect WRITE setMultiSelect)
    
        /*
         * QML property to read the selected filenames
         */
        Q_PROPERTY(QVariant filepaths READ getFilePaths)
    
        /*
         * QML property to set or get the file filters. This is an
         * list array variant.
         */
        Q_PROPERTY(QVariant filters READ getFilters WRITE setFilters)
    public:
        /*
         * Ctor and Dtor
         */
        FileBrowseDialog(QObject* parent = 0);
        virtual ~FileBrowseDialog();
    
        /*
         * Exposed to QML to start the run loop which creates and displays the dialog.
         * The dialog is shown until a button is clicked.
         */
        Q_INVOKABLE void show();
    
    public:
        /*
         * Getter for the selected filenames QML property
         */
        QVariant getFilePaths() const;
    
        /*
         * Setter and Getter for the filters QML property
         */
        QVariant getFilters() const;
        void setFilters(QVariant const& value);
    
        /*
         * Getter and Setter for the multiselect QML property
         */
        bool getMultiSelect() const;
        void setMultiSelect(bool value);
    
    signals:
        /*
         * Signal emitted when the OK button has been clicked on the browse dialog
         * The OK button is not enabled unless a file is selected
         */
        void selectionCompleted();
    
        /*
         * Signal emitted when the cancel button has been clicked on the browse dialog
         */
        void selectionCancelled();
    
    protected:
        /*
         * Implements the run loop. Dialog stays open until a button is clicked.
         */
        virtual void run();
    
    protected:
        dialog_instance_t m_dialog;
        bool m_multiSelect;
        QVariantList m_filePaths;
        QVariantList m_filters;
    };
    
    #endif /* FILEBROWSEDIALOG_HPP_ */
    

    FileBrowseDialog.cpp

    #include "FileBrowseDialog.hpp"
    #include 
    #include 
    
    FileBrowseDialog::FileBrowseDialog(QObject* parent)
        : QThread(parent)
        , m_multiSelect(false)
    {
        m_filters.push_back(QString("*.*"));
    }
    
    FileBrowseDialog::~FileBrowseDialog()
    {
    }
    
    void FileBrowseDialog::show()
    {
        if (!isRunning())
        {
            m_filePaths.clear();
            start();
        }
    }
    
    QVariant FileBrowseDialog::getFilePaths() const
    {
        return m_filePaths;
    }
    
    bool FileBrowseDialog::getMultiSelect() const
    {
        return m_multiSelect;
    }
    
    void FileBrowseDialog::setMultiSelect(bool value)
    {
        m_multiSelect = value;
    }
    
    QVariant FileBrowseDialog::getFilters() const
    {
        return m_filters;
    }
    
    void FileBrowseDialog::setFilters(QVariant const& value)
    {
        m_filters = value.toList();
        qDebug() << "filter count: " << m_filters.count();
    }
    
    void FileBrowseDialog::run()
    {
        bps_initialize();
    
        //request all dialog events
        dialog_request_events(0);
        if (dialog_create_filebrowse(&m_dialog) != BPS_SUCCESS)
        {
            qDebug() << "Failed to create file browse dialog.";
            emit selectionCancelled();
            return;
        }
    
        //set the selection filters
        if (m_filters.count() > 0)
        {
            char** ext = (char**)new char[m_filters.count()*sizeof(char*)];
            int i = 0;
            for (QVariantList::iterator it = m_filters.begin(); it != m_filters.end(); ++it, ++i)
            {
                QString filter = it->toString();
                if (!filter.trimmed().isEmpty())
                {
                    int length = (filter.length() + 1) * sizeof(char);
                    ext[i] = new char[length];
                    strncpy(ext[i], filter.toAscii(), length);
                }
            }
            if (dialog_set_filebrowse_filter(m_dialog, (const char**)ext, m_filters.count()) != BPS_SUCCESS)
            {
                qDebug() << "unable to set file browse dialog extensions";
            }
            for (i = 0; i < m_filters.count(); i++)
            {
                delete ext[i];
            }
            delete ext;
        }
    
        if (dialog_show(m_dialog) != BPS_SUCCESS)
        {
            qDebug() << "Failed to show file browse dialog.";
            dialog_destroy(m_dialog);
            m_dialog = 0;
            emit selectionCancelled();
            return;
        }
    
        bool shutdown = false;
        while (!shutdown)
        {
            bps_event_t* event = NULL;
            bps_get_event(&event, -1);    // -1 means that the function waits
            // for an event before returning
    
            if (event)
            {
                if (bps_event_get_domain(event) == dialog_get_domain())
                {
                    //0=ok, 1=cancel
                    int selectedIndex = dialog_event_get_selected_index(event);
    
                    if (selectedIndex == 1)
                    {
                        int count;
                        char** filepaths;
                        if (BPS_SUCCESS == dialog_event_get_filebrowse_filepaths(event, &filepaths, &count))
                        {
                            for (int i = 0; i < count; i++)
                            {
                                qDebug() << "selected file: " << filepaths[i];
                                m_filePaths.push_back(QString(filepaths[i]));
                            }
                            bps_free(filepaths);
                        }
                        emit selectionCompleted();
                    }
                    else
                    {
                        emit selectionCancelled();
                    }
    
                    qDebug() << "Got file browse dialog click";
                    shutdown = true;
                }
            }
        }
    
        if (m_dialog)
        {
            dialog_destroy(m_dialog);
        }
    }
    

    This class derives from QObject (by QThread) which means that it can be used by QML when it exposes properties and signals. The FileBrowseDialog class has 3 properties

    -multiple selection: a Boolean flag indicating if single or multiple selection is allowed

    -filepaths: a read only value that returns the list of files selected

    -Filters: a read/write value is where you can specify one or more filters to file (for example, ".doc", "*.jpg") etc.

    The next part is how you call the FileBrowseDialog through the QML. To do this, we must inform the QML of the FileBrowseDialog page. This is done in the App class via the qmlregistertype code.

    App.cpp

    #include 
    #include 
    #include 
    
    #include "app.hpp"
    #include "FileBrowseDialog.hpp"
    
    using namespace bb::cascades;
    
    App::App()
    {
        qmlRegisterType("Dialog.FileBrowse", 1, 0, "FileBrowseDialog");
        QmlDocument *qml = QmlDocument::create("main.qml");
        qml->setContextProperty("cs", this);
    
        AbstractPane *root = qml->createRootNode();
        Application::setScene(root);
    }
    

    The QML is now ready to be able to use the FileBrowseDialog. The example below is a page complete qml which has a button and a label. When we click on the FileBrowseDialog button is open, and all selected files will appear in the label.

    Main.QML

    import bb.cascades 1.0
    import Dialog.FileBrowse 1.0
    
    Page {
        content: Container {
            Label { id: filebrowseDialogLabel }
            Button {
                text : "File Browse Dialog"
                onClicked: {
                    filebrowseDialog.show();
                }
            }
            attachedObjects: [
                FileBrowseDialog {
                    id: filebrowseDialog
                    multiselect : true
                    filters : ["*.doc","*.jpg","*.txt"]
                    onSelectionCompleted: {
                        if(filebrowseDialog.filepaths.length>0)
                            filebrowseDialogLabel.text = filebrowseDialog.filepaths[0];
                        else
                            filebrowseDialogLabel.text = "no file selected";
                    }
                    onSelectionCancelled: {
                        filebrowseDialogLabel.text = "file browse dialog was cancelled";
                    }
                }
            ]
        }
    }
    

    And it's pretty much just invoke the native dialog file navigation in stunts. Please note save the file would follow a similar model, but I found that this dialog box was not particularly useful because it displays only a simple dialogbox with a text file name entry.

    See you soon

    Swann

Maybe you are looking for