Integrating the QUdpSocket Class into QML



  • Hi all,

    I'm a newbie with Qt, and so I'm quite a bit unfamiliar with its inner workings. I'm currently using Qt 5.2 on a Windows 7 machine trying to make a UDP portal. I also hardly know C++, I mostly just use C on embedded processors. But I need this specific program, and since one doesn't exist, I need to make it. Please be patient if I'm asking this incorrectly... I have read the datasheets and it's still a little abstract to me...

    I want to embed the QUdpSocket class into my QML code so that when buttons are clicked, I can call that class function to send a datagram. I have the QML code for the buttons, and now am trying to figure out how to embed the C++ class into the code. Is it as simple as this to allow me to use the class functions?

    @ import QUdpSocket @

    and then, to call the writeDatagram function from a button, I just simply need the following (using general function description)?

    @Button {
    id: autoupdate
    x: 340
    y: 56
    text: "AutoUpdate"
    signal clicked
    onClicked: QUdpSocket.writeDatagram()
    }@

    Is it that simple? Or am I missing a step?

    (pardon the generic writeDatagram() - trying to make an easier read).


  • Moderators

    Hi, and welcome to the Qt Dev Net!

    [quote author="jediengineer" date="1391439678"]I also hardly know C++, I mostly just use C on embedded processors.[/quote]C++ has many similarities with C. For now, just think of a C++ class as a C struct which has functions attached to it.

    The most important difference here lies in event-driven programming. This isn't a feature of C++ itself, but most of Qt's classes (including QUdpSocket) are designed to be used in an event-driven way. Think of events as interrupts.

    Signals are interrupts, and slots are interrupt handlers.

    [quote]I have the QML code for the buttons, and now am trying to figure out how to embed the C++ class into the code. Is it as simple as this to allow me to use the class functions?

    @ import QUdpSocket @
    [/quote]No, you cannot import C++ classes directly into QML.

    My post on 28 September 2013 shows 2 ways of calling a C++ function from QML: https://qt-project.org/forums/viewthread/33011/#144473

    Note: Only slots, or functions marked with the "Q_INVOKABLE macro":http://qt-project.org/doc/qt-5/qobject.html#Q_INVOKABLE, can be called from QML.

    [quote](pardon the generic writeDatagram() - trying to make an easier read).[/quote]Please don't apologize, because this is a good way to show others what you're thinking! :)

    Also, please feel free to ask more questions if you have any.



  • Thanks JKSH, I appreciate you taking the time to answer a few questions from someone pretty new. I normally am a hardware designer, but I kind of got thrown into software this year with no warning, so it's learn as you go for me.

    Bear with me, let me see if I understand all this correctly... So I'm trying to make a simple GUI that has several buttons and check boxes. when you click a button, it sends a 16bit number datagram to an IP address and port number specified in a text box. Most of QML as I've seen appears to be intuitive, but some of this eludes me. So if I want to use the QudpSocket Class in QML, could I simply do this?

    @
    class Sockets : public QObject
    {
    Q_OBJECT
    public:
    Q_INVOKABLE QUdpSocket writeDatagram ();
    }
    };
    @

    or would it be better to create a class with my own functions that invoke members of the QUdpSocket Class?

    So then from the QML side, I would encode a button like this:

    @ Button {
    id: step_DAC
    x: 106
    y: 408
    text: "DAC Step"
    signal clicked

        MouseArea {
        anchors.fill: button
        onClicked: { my_udp_socket_Function();}
      }
    }@
    

    Then in the main function on the C++ side I would have (from your post):

    @ int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv);

        // Create and show your QML GUI
        QQuickView *view = new QQuickView(QUrl("main.qml"));
        view->show();
     
        // Get a pointer to your QML item and C++ object
        QQuickItem *item = view->rootObject();
        MyObject *obj = new MyObject();
     
        // 1) Connect the QML signal to a C++ slot
        QObject::connect(item, SIGNAL(my_udp_socket_function());
     
        // 2) Allow the QML file to call MyObject's C++ slots directly
        view->rootContext()->setContextProperty("myObj", obj);
     
        return app.exec();
    }
    

    @

    to my knowledge and understanding, I'll submit that I believe I don't need a slot if I'm only calling one function?


  • Moderators

    [quote author="jediengineer" date="1391523875"]Thanks JKSH, I appreciate you taking the time to answer a few questions from someone pretty new. I normally am a hardware designer, but I kind of got thrown into software this year with no warning, so it's learn as you go for me.[/quote]You're welcome! I hope you find your foray into software an enjoyable and enriching experience.

    [quote]So I'm trying to make a simple GUI that has several buttons and check boxes. when you click a button, it sends a 16bit number datagram to an IP address and port number specified in a text box.[/quote]Ok, so you need to do 3 separate things:

    Read the IP address and port number from the text box

    Establish a connection to the address+port from Step #1

    Send the 16-bit number through the connection

    So far, you've talked about calling a function to write the datagram (Step #3). Your next exercise is to think about how to do #1 and #2. How would you do it in C?

    This page should also help: http://qt-project.org/doc/qt-5/QUdpSocket.html

    [quote]So if I want to use the QudpSocket Class in QML, could I simply do this?

    @
    class Sockets : public QObject
    {
    Q_OBJECT
    public:
    Q_INVOKABLE QUdpSocket writeDatagram ();
    }
    };
    @
    [/quote]Yes, you can definitely call your invokable writeDatagram() function in response to a click. But they way it's currently written, writeDatagram() returns a QUdpSocket object, which I'm sure isn't what you intended.

    Are you familiar with calling functions and getting their return values?

    [quote]or would it be better to create a class with my own functions that invoke members of the QUdpSocket Class?[/quote]Your Sockets class above actually fits this description. :) Yes, this is the way to go, because you cannot call QUdpSocket's functions from QML. The relevant functions are neither slots nor invokables.

    [quote]So then from the QML side, I would encode a button like this:

    @ Button {
    id: step_DAC
    x: 106
    y: 408
    text: "DAC Step"
    @
    [/quote]All good so far.
    [quote]
    @
    signal clicked

        MouseArea {
        anchors.fill: button
        onClicked: { my_udp_socket_Function();}
      }
    }@
    

    [/quote]Two issues here:

    The Button object already has a clicked() signal (see http://qt-project.org/doc/qt-5/qml-qtquick-controls-button.html ). Do not add it yourself.

    The Button object already handles mouse events, and automatically emits the clicked() signal when you click. You don't need to add your own MouseArea -- you only need it for objects that don't have built-in mouse handling functionality.

    [quote]Then in the main function on the C++ side I would have (from your post):

    @
    ...
    // 1) Connect the QML signal to a C++ slot
    QObject::connect(item, SIGNAL(my_udp_socket_function());

        // 2) Allow the QML file to call MyObject's C++ slots directly
        view->rootContext()->setContextProperty("myObj", obj);
    

    ...
    @
    /quote and (2) are two different ways to achieve the same thing; you only need one of them. I'd recommend (1), because it lets you get used to signals and slots, which are one of Qt's most useful features. QML code also relies on signals+slots a lot for interaction.

    [quote]to my knowledge and understanding, I'll submit that I believe I don't need a slot if I'm only calling one function? [/quote]That's incorrect, I'm afraid. Have a read through my post on 29 January: http://qt-project.org/forums/viewthread/37001/P30/#160320 It is a short intro to signals and slots. Then, come back with your modified code.

    I hope this is helpful to you; please let me know if I'm going too slowly.



  • Thanks JKSH, and you're not going too slow at all or too fast for that matter. But you're definitely helping my transition! So, just a little about my project, so you'll understand where I'm coming from: I designed and built a power supply controller and programmed the software (in C) into a NetBurner core module.
    Unfortunately, the controller is meant to interact with a program via network using UDP. Nothing exists (yet) for me to test my embedded device, so I'm making it myself. This is where I'm a bit out of my league, but catching up quick. The program I'm trying to write has several buttons that when clicked send a small datagram to the embedded processor. One or two of the buttons have a checkbox or a text input next to them for added data, but that's the gist of it. Again, being new to writing windows software, and GUIs, and Qt in general, your help is most appreciated, and you've been kind enough to give examples and explain rather than to just point me to a datasheet. I won't forget it!

    So your post on slots and functions has enlightened me a little. I'll be reading into it and seeing if I can further integrate it into my code. I have consolidated my code a little better, turns out when I was dragging and dropping the widgets, it did not put all the children in their proper places. So now, a revised code is shown below:

    QML:

    @ Button {
    id: step_DAC
    x: 106
    y: 408
    text: "DAC Step"
    onClicked: { sys_dac_step();} // insert function here

        CheckBox {
            id: checkBox1
            x: 86
            y: 3
            text: "Fine Step"
        }
        
        CheckBox {
            id: checkBox3
            x: 167
            y: 3
            text: "UP"
        }
    
    }@
    

    So for starters, I began by making a class of all my functions here's a few to save space, also it's incomplete, but getting there):

    C/CPP:

    @
    class TLA_Funcs
    {
    public:
    void sys_enable(void);
    void sys_inhibit(void);
    void sys_disable(void);
    void sys_self_check(void);
    protected:
    bool sys_recd;
    bool sys_sent;
    // more to come...
    }TLA_FUNCS;@

    Then an object from that class, which is making me wonder if my class is redundant in some form:

    @class LambdaFunc : public QObject
    {
    Q_OBJECT
    public: // these are the functions that will be used by the signals from the gui
    Q_INVOKABLE TLA_FUNCS sys_enable();
    Q_INVOKABLE TLA_FUNCS sys_inhibit();
    Q_INVOKABLE TLA_FUNCS sys_disable();
    Q_INVOKABLE TLA_FUNCS sys_self_check();
    protected:
    // need to figure out if anything is needed here, doubtful at the moment
    };@

    These are the functions called by the buttons. Following your lead, I'll go with the signals and slots method so I can learn them better, and my main routine will have a slot connection to each signal. Now I'm assuming that in place of "item" I would use the item name? such as "button" or "checkbox", and if so, I'll correct that asap, but if not, since there are several buttons, this is what I have in my main method:

    @int main (int argc, char*argv[]) {

    QGuiApplication app(argc, argv);
    
    QQuickView *view = new QQuickView(QUrl("TLA_UDP_Portal.qml"));
    view->show();
    
    QQuickItem *item = view->rootObject();  // unsure how to handle these two
    MyObject *obj = new MyObject();              // or if I need one instance of these per slot... 
    
    QObject::connect(item, SIGNAL(sys_enable());
    QObject::connect(item, SIGNAL(sys_inhibit());
    QObject::connect(item, SIGNAL(sys_disable());
    QObject::connect(item, SIGNAL(sys_self_check());
    

    // . . .
    @

    My assumption is that each "item" needs to be replaced with a descriptor like "button.enable" so that the final object slot connection would be this:

    @ Object::connect(button.enable, SIGNAL(sys_enable());@

    Am I correct? And if I understand this correctly, this will automatically call the function specified when the button is clicked?

    I also need to read the status of the checkboxes and text inputs. Especially those that have the IP address, and port numbers. I couldn't find a function to handle converting the port address, so I wrote it myself. That wasn't too big of a deal. It's crude at the moment, but a start. I did find a method which led me to this:

    @quint64 ipAddress = QHostAddress(textInput.textInput1.text).toIPv4Address();@

    So that's taken care of. But as for reading the checkboxes and text in general, let me take a stab at it... So there's the parent button, with the two checkbox children in my sample code I pasted. Am I correct to assume, based on this thread: http://qt-project.org/forums/viewthread/8485 - that to retrieve the state of the checkbox, I would need to do the following:

    @ QSettings settings;

    // point directly to the particular checkbox names
    QCheckBox* left_INV=ui->left_INV;   // this is the name of the checkbox that is the first child of the enable button
    QCheckBox* right_INV=ui->right_INV;   // this is the name of the checkbox that is the second child of the enable button
    
    
    // to load the checkbox settings (I'm assuming this makes left_INV and right_INV a bool value for each?):
            
    left_INV->setChecked(settings.value("checkstate").toBool());
    right_INV->setChecked(settings.value("checkstate").toBool());@
    

    after which, C code could address as such:

    @if (left_INV){
    // stuff, etc...
    }@

    This is a lot, sorry if it's too long. Hopefully I got it right...



  • Hi JKSH - pleas hold off on responding until my next post - I might need to correct my last response...



  • Hi JKSH,

    I can't find the documentation on the connect function. I can't find the 2 argument version of connect in the existing documentation, yet it compiles... Can you point me to a reference that shows the 2 argument version of connect?


  • Moderators

    Hi jediengineer,

    There is no 2-argument version of connect(). All of them are listed in the "QObject documentation":http://qt-project.org/doc/qt-5/qobject.html#connect, and all of them require at least 3 things:

    • The sender (signal emitter)
    • The signal
    • The slot

    And if your sender and receiver are different objects (which is true in your case), you also need to provide a 4th argument:

    • The receiver

    I'll respond to the rest of your post in detail soon.



  • Thanks!! I worked on a few things over the weekend, and noticed that my code just wouldn't compile no matter what. The compiler showed that it had autodetected MinGW, but it still wouldn't compile. I have since uninstalled and re-installed Qt, and everything compiles just fine now. It actually compiled with no errors, but I am getting "function() not defined" for my functions, which I haven't set up yet completely. Anyways, I'll wait for your response before I post the rest.


  • Moderators

    Hi jediengineer,

    Your QML code is looking good!

    [quote]
    So for starters, I began by making a class of all my functions...
    @
    class TLA_Funcs
    {...}
    @

    Then an object from that class, which is making me wonder if my class is redundant in some form:
    @
    class LambdaFunc : public QObject
    {...}
    @
    [/quote]A quick intro to some terminologies in object-oriented programming:

    • A class is like a blueprint or schematic or technical drawing. It describes how an object should be built.
    • An object is an actual instance (like a manifestation or a copy) of a class.

    So using your example code, both TLA_Funcs and LambdaFunc are classes. You can create TLA_Funcs objects like this:
    @
    int main() {
    TLA_Funcs t1_stack;
    TLA_Funcs* t2_heap = new TLA_Funcs();

    ...
    
    return 0;
    

    }
    @

    t1_stack is an instance of the TLA_Funcs class that is allocated on the stack, t2_heap is an instance of the TLA_Funcs class that is allocated on the heap. The new keyword in C++ is like a smarter version of malloc fromC (have you used this before?).

    So, you don't need to have both TLA_Funcs and LambdaFunc. Just one will do.

    And, you only need to create one instance of your class, to manage your UDP connection and to listen for your QML signals.

    [quote]
    @TLA_FUNCS sys_enable();@
    [/quote]I'm not sure what you're trying to do here. This says: Every time you call sys_enable(), it returns a copy of TLA_FUNCS when it is done. Can you explain your train of thought in more detail?

    Anyway, I'll make your TLA_Funcs class into a QObject class, because you probably don't want your slots to return anything:
    @
    class TLA_Funcs : public QObject
    {
    Q_OBJECT
    public slots:
    void sys_enable(void);
    void sys_inhibit(void);
    void sys_disable(void);
    void sys_self_check(void);
    protected:
    // ...
    };

    // Or, the above can also be written as:
    class TLA_Funcs : public QObject
    {
    Q_OBJECT
    public:
    Q_INVOKABLE void sys_enable(void);
    Q_INVOKABLE void sys_inhibit(void);
    Q_INVOKABLE void sys_disable(void);
    Q_INVOKABLE void sys_self_check(void);
    protected:
    // ...
    };
    @

    [quote]
    @
    QQuickItem *item = view->rootObject(); // unsure how to handle these two
    MyObject *obj = new MyObject(); // or if I need one instance of these per slot...

    QObject::connect(item, SIGNAL(sys_enable());
    QObject::connect(item, SIGNAL(sys_inhibit());
    QObject::connect(item, SIGNAL(sys_disable());
    QObject::connect(item, SIGNAL(sys_self_check());
    

    @
    [/quote]The QQuickItem instance represents your QML file. The MyObject instance is the object that listens for the QML signals. So in your case, replace MyObject with TLA_Funcs. You only need one instance for your entire program.

    [quote]My assumption is that each “item” needs to be replaced with a descriptor like “button.enable” so that the final object slot connection would be this:
    @Object::connect(button.enable, SIGNAL(sys_enable());@

    Am I correct? And if I understand this correctly, this will automatically call the function specified when the button is clicked?
    [/quote]No. Multiple issues here:

    • "item" refers to your object that receives the signals. It must be retained.
    • sys_enable() is a slot, not a signal.
    • Like I said before, in all calls to connect(), you must specify 4 things: the sender, the signal, the receiver, and the slot.

    So you want something like this:
    @
    QQuickItem* item = view->rootObject();
    TLA_Funcs* funcs = new TLA_Funcs();

    QObject::connect(item, SIGNAL(buttonClicked_enable()),
    funcs, SLOT(sys_enable()));
    @

    The buttonClicked_enable() signal doesn't exist yet, so we add it to your QML file:

    @
    // TLA_UDP_Portal.qml
    Rectangle {
    // Declare the signal
    signal: buttonClicked_enable()

    Button {
        id: enable_button
        x: 106
        y: 408
        text: "Enable"
    
        // Emit the signal
        onClicked: buttonClicked_enable()
    }
    

    }
    @

    Now, every time the Button emits the clicked() signal, your TLA_UDP_Portal will also emit the buttonClicked_enable() signal. We have to do it this way because the Button is "hidden" inside TLA_UDP_Portal, so the Button's signals are not accessible from the C++ side.

    Then, when the buttonClicked_enable() signal is emitted, it will call the sys_enable() slot.

    There are a few more paragraphs, I'll address them in a later post. Hope this is enough for some progress!



  • JKSH - this is fantastic. I think I understand the slot much better from your example, thanks!!

    Malloc - yes, I've used it before, not often in the DSP work I've done, but I have used it. With your example of:
    @TLA_Funcs* t2_heap = new TLA_Funcs();@
    normally, you would need to release it with @delete TLA_Funcs;@ would you not? Or is that what @return 0;@ is for? I've never used it with a return. My program should only call the instance of it once though, so I'm not sure I shouldn't need to delete it. I am still trying to determine if I need an endless loop in the main() function to address the incoming packets, and to modify the textbox to output the data coming back from the embedded device... but after reading up on the QML Socket Class, I believe I may not...

    So as you were writing your response, I went to cplusplus.com and ran through the class structure, and you re0inforced it. My only shortcoming was understanding the way to use it with Q_INVOKABLE - I assumed you had to have a pre-existing class (from reading the Qt notes) in order to to make it's functions Q_INVOKABLE. Thankfully, I now know better. So my class is now this so far, as per your lead:

    @class TLA_Funcs : public QObject
    {
    Q_OBJECT
    public slots:
    Q_INVOKABLE void sys_enable(void);
    Q_INVOKABLE void sys_inhibit(void);
    Q_INVOKABLE void sys_disable(void);
    Q_INVOKABLE void sys_force_idle(void);
    Q_INVOKABLE void sys_autoupdate(void);
    Q_INVOKABLE void sys_reset(void);
    Q_INVOKABLE void sys_observe(void);
    Q_INVOKABLE void sys_dac_test(void);
    Q_INVOKABLE void sys_reset_dac(void);
    Q_INVOKABLE void sys_read_adc(void);
    Q_INVOKABLE void sys_read_mux(void);
    Q_INVOKABLE void sys_poll(void);
    Q_INVOKABLE void sys_set_dac(void);
    Q_INVOKABLE void sys_cpu_reset(void);
    Q_INVOKABLE void sys_dac_step(void);
    Q_INVOKABLE void sys_cpu_halt(void);
    Q_INVOKABLE void sys_self_check(void);
    protected:
    // to be added later
    };@

    I also looked in my QML code, and I didn't have the @signal: buttonClicked_enable()@ in my code. I'm assuming that I need to define one signal per button and checkbox in the parent rectangle? So I would have:

    @Rectangle {
    id: main
    width: 640
    height: 480
    color: "#a9cde8"
    border.width: 4
    border.color: "#000000"

    signal buttonClicked_enable()
    signal buttonClicked_Disable()
    signal checkbox_Checked1()
    signal checkbox_Checked2() 
    
    Button {
        id: enable
        x: 106
        y: 408
        text: "Enable"
        onClicked buttonClicked_enable()
    
        CheckBox {
            id: left_only1
            x: 86
            y: 3
            text: "LEFT"
            onClicked checkbox_Checked1()
        }
     }
    
    Button {
        id: disable
        x: 106
        y: 408
        text: "Disable"
        onClicked buttonClicked_disable()
    
        CheckBox {
            id: left_only2
            x: 86
            y: 3
            text: "LEFT"
            onClicked checkbox_Checked2()
        }
     }
    

    }@

    Also, I get an error when I use a colon after signal, so I removed it and it builds with no errors. So then on my C++ side, I would now have in my main function:

    @int main (int argc, char*argv[]) {

    QGuiApplication app(argc, argv);
    
    QQuickView *view = new QQuickView(QUrl("TDK_Lambda_UDP_Portal.qml"));  
    view->show();                                                           
    QQuickItem *item = view->rootObject();                                 
    TLA_Funcs *obj = new TLA_Funcs();       
    
    QObject::connect(item, SIGNAL(buttonClicked_enable()), funcs, SLOT(sys_enable());
    QObject::connect(item, SIGNAL(checkbox_Checked1()), funcs, SLOT(chkbox1());
    QObject::connect(item, SIGNAL(buttonClicked_disable()), funcs, SLOT(sys_disable()); 
    QObject::connect(item, SIGNAL(checkbox_Checked2()), funcs, SLOT(chkbox2());@
    

    This seems to build just fine, so I will try making a dummy function today to see if I did it right. Hopefully, writing back to a text box will be similar!!


  • Moderators

    [quote]normally, you would need to release it with
    @delete TLA_Funcs;@
    would you not?[/quote]Correct. :) I did not show complete code (that's what the "..." was for)

    [quote]My program should only call the instance of it once though, so I’m not sure I shouldn’t need to delete it.[/quote]More precisely, you want to create one instance of TLA_Funcs, and keep it for as long as your program runs. That instance will receive all signals from your QML code, and its slots will be executed in response to those signals.

    Thus, you wouldn't delete your instance until you are shutting down your program.

    [quote]Or is that what
    @return 0;@
    is for? I’ve never used it with a return.[/quote]return passes the result of this function back to whoever called the function -- See http://www.cplusplus.com/doc/tutorial/functions/ . Functions that don't return anything have "void" as their return type.

    That's why I said earlier to make your slots return "void", not "TLA_FUNCS".

    [quote]So my class is now this so far, as per your lead:
    @
    class TLA_Funcs : public QObject
    {
    Q_OBJECT
    public slots:
    Q_INVOKABLE void sys_enable(void);
    Q_INVOKABLE void sys_inhibit(void);
    ...
    }
    @
    [/quote]You only need one of "public slots" or "Q_INVOKABLE". Having both is redundant.

    [quote]I also looked in my QML code, and I didn’t have the
    @signal: buttonClicked_enable()@
    in my code. I’m assuming that I need to define one signal per button and checkbox in the parent rectangle?

    ...

    Also, I get an error when I use a colon after signal[/quote]I apologize for the typo in my last post. You're right, there should be no colon after "signal".

    There needs to be a colon after "onClicked" though :)

    The rest of your QML code looks fine.

    You might notice that it gets tedious to add so many signals (one per button). Once you've mastered this method, I'll show you the shorter way of calling C++ functions from QML.

    [quote]
    @
    TLA_Funcs *obj = new TLA_Funcs();

    QObject::connect(item, SIGNAL(buttonClicked_enable()), funcs, SLOT(sys_enable());
    @
    [/quote]You don't have a "funcs" object -- you called your object "obj" instead. So the name you use in the connection must match.

    Note that connections and QML code are not checked at compile-time -- you will only see run-time error messages.



  • JKSH -

    Sorry, it slipped my mind with the "return 0" - Most of the "void main(void *pd)" (in my case) functions that I use have always had an endless while(1) loop inside, and never needed the "return 0" - but yes, you're right, void functions always return 0, or just return (depending).

    As for the Q_OBJECT and Q_INVOKABLE, I didn't realize they were redundant within the class - I saw an example which I'm struggling to locate, which had it that way, so I took that lead.

    Also, "obj" was a typo - I did actually call it "funcs" - sorry about that. I am curious as to that shorter method of calling C++ functions... :-)



  • Ok, so I've entered my signals as you have explained:

    @signal buttonClicked_enable()@
    and in the button description:
    @onClicked:buttonClicked_enable()@

    On the C++ side:

    @QQuickItem *button = view->rootObject;
    TLA_Funcs *funcs = new TLA_Funcs();
    QObject::connect(button, SIGNAL(buttonClicked_enable()), funcs, SLOT(sys_enable());@

    Which should be correct if I'm not mistaken. My functions are slotted in the class, and I'm still defining the functions. Part of these functions rely on several checkboxes near the button - so when I enable both halves of the system, I would check both checkboxes. On the C++ side, I have to check the state of those checkboxes, so if I read right, I should be able to do that as such:

    @QSettings settings;
    QCheckBox* left_INV=ui->left_INV;
    QCheckBox* right_INV=ui->right_INV;@

    and this should create an instance of the checkboxes for my code to access the parameters, correct? Then I would read the checked state as a bool value like so:

    @ left_INV->setChecked(settings.value("checkstate").toBool());
    right_INV->setChecked(settings.value("checkstate").toBool());@

    This should make left_INV and right_INV a boolean value that I can refer to in my code, if I'm not mistaken.

    I'm going to try adding one full function so that I can check functionality after I build it, and will let you know if I get hung up...


  • Moderators

    [quote author="jediengineer" date="1392133256"]Ok, so I've entered my signals as you have explained:

    @signal buttonClicked_enable()@
    and in the button description:
    @onClicked:buttonClicked_enable()@

    On the C++ side:

    @QQuickItem *button = view->rootObject;
    TLA_Funcs *funcs = new TLA_Funcs();
    QObject::connect(button, SIGNAL(buttonClicked_enable()), funcs, SLOT(sys_enable());@
    Which should be correct if I'm not mistaken.
    [/quote]Yep, looks good, except for some typos (you have mismatched parantheses).

    One very tiny nitpick: Your QQuickItem represents multiple buttons, so I'd pick a different name to "button". :)

    [quote]But as for reading the checkboxes and text in general, let me take a stab at it… So there’s the parent button, with the two checkbox children in my sample code I pasted. Am I correct to assume, based on this thread: http://qt-project.org/forums/viewthread/8485 – that to retrieve the state of the checkbox, I would need to do the following:
    @
    QSettings settings;

    // point directly to the particular checkbox names
    QCheckBox* left_INV=ui->left_INV;   // this is the name of the checkbox that is the first child of the enable button
    QCheckBox* right_INV=ui->right_INV;   // this is the name of the checkbox that is the second child of the enable button
    
    
    // to load the checkbox settings (I'm assuming this makes left_INV and right_INV a bool value for each?):
           
    left_INV->setChecked(settings.value("checkstate").toBool());
    right_INV->setChecked(settings.value("checkstate").toBool());
    

    @
    [/quote]No. That thread is talking about a checkbox -- an actual graphical user interface component -- implemented in C++. You currently have checkboxes in QML.

    It is important to note: A C++ QCheckBox is completely unrelated to a QML CheckBox. Qt Widgets (C++) and Qt Quick (QML) are completely different technologies for creating user interfaces.

    Also, a QSettings class is for storing program settings into your hard drive. You don't need it (unless you want to do fancy things like... store the IP address on disk).

    If you want, you can use C++ widgets to create your user interface for testing your UDP connection to your hardware. But you're almost there with QML, so I'd recommend persevering with QML :)

    [quote]after which, C code could address as such:
    @
    if (left_INV){
    // stuff, etc...
    }
    @
    [/quote]Again, no. You have defined left_INV as a pointer to a QCheckBox object -- this is not the checkbox's value. If you call if() on a pointer, it will return true if the pointer is not null.

    The correct way to check a QCheckBox's state is:
    @if (left_INV->isChecked())@

    (But since you're using a QML CheckBox and not a C++ QCheckBox, you don't need this)

    I wrote up to here, then noticed your other investigation at http://qt-project.org/forums/viewthread/38342/ . I'll see if there's anything I can add there.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.