Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Variable to select textfield in QML

Variable to select textfield in QML

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 2 Posters 854 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Dave_022
    wrote on last edited by
    #1

    I am attempting to build on code that allows me to click a send button to send a value to Serial and then update the textfield associated with it with numbers returned. I can't work out how to control which text field is being updated without creating seperate instances for all of them?

    arduinoserial.h

    #include <QObject>
    #include <QSerialPort>
    
    class ArduinoSerial : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString droValue READ droValue WRITE setDroValue NOTIFY droValueChanged)
        Q_PROPERTY(QString lcdToUpdate READ lcdToUpdate WRITE setLcdToUpdate NOTIFY lcdToUpdateChanged)
    
    public:
        ArduinoSerial();
        QString droValue() const;
        QString lcdToUpdate() const;
    
    public slots:    
        void startSerialPort(); // Starts the Open Serial Port Function
        void readSerial();
        void setDroValue(const QString& value);
        void closeSerialPort();
        void writeSerial(const QByteArray &data);
        void setLcdToUpdate(const QString &value);
    
    
    signals:
        void serialPortOpen(); // Signal for sucessfully opening Serial Port
        void serialPortEror(); // Signal on not finding arduino in openSerialPort
        void droValueChanged(); // Signal on data received from arduino
        void lcdToUpdateChanged(); // Signal on setting value for which lcd to use
    
    private:
        QSerialPort *arduino;
        static const quint16 arduino_uno_vendor_id = 9025;
        static const quint16 arduino_uno_product_id = 67;
        QString arduino_port_name;
        bool arduino_is_available;
        QString m_droValue;
        QString m_lcdToUpdate;
    
        void openSerialPort();
    };
    
    #endif // ARDUINOSERIAL_H
    
    

    arduinoserial.cpp

    #include "arduinoserial.h"
    #include <QDebug>
    #include <QSerialPort>
    #include <QSerialPortInfo>
    
    ArduinoSerial::ArduinoSerial()
    {   
    
    }
    
    QString ArduinoSerial::droValue() const
    {
        return m_droValue;
    }
    
    QString ArduinoSerial::lcdToUpdate() const
    {
        return m_lcdToUpdate;
        qDebug() << lcdToUpdate();
    }
    
    void ArduinoSerial::startSerialPort()
    {
        this->openSerialPort();
    }
    
    void ArduinoSerial::readSerial()
    {   
        // Read data
        static QByteArray byteArray;
        byteArray += arduino->readAll();
    
        //we want to read all message not only chunks
        if(!QString(byteArray).contains("\n"))
            return;
    
        //sanitize data
        QString data = QString( byteArray ).remove("\r").remove("\n");
        byteArray.clear();
    
        // Print data
        qDebug() << "RECV: " << data;
        setDroValue(data);
        droValueChanged();
    }
    
    void ArduinoSerial::setDroValue(const QString& value)
    {
        if (m_droValue != value) {
            m_droValue = value;
            droValueChanged();
        }
    }
    
    void ArduinoSerial::closeSerialPort()
    {
        if(arduino->isOpen()){
            arduino->close();
        }
        qDebug() << "Seriol Port is closed";
    }
    
    void ArduinoSerial::writeSerial(const QByteArray &data)
    {
       arduino->write(data);
       qDebug() << (data) + " written to serial";
    }
    
    void ArduinoSerial::setLcdToUpdate(const QString &value)
    {
        if(m_lcdToUpdate !=value) {
            m_lcdToUpdate = value;
            lcdToUpdateChanged();
            qDebug() << m_lcdToUpdate;
        }
    }
    
    void ArduinoSerial::openSerialPort()
    {
        /*
         *   Identify the port the arduino uno is on.
         */
        arduino = new QSerialPort;
        arduino_is_available = false;
        arduino_port_name = "";
    
        //
        //  For each available serial port
        foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()){
            //  check if the serialport has both a product identifier and a vendor identifier
            if(serialPortInfo.hasProductIdentifier() && serialPortInfo.hasVendorIdentifier()){
                //  check if the product ID and the vendor ID match those of the arduino uno
                if((serialPortInfo.productIdentifier() == arduino_uno_product_id)
                        && (serialPortInfo.vendorIdentifier() == arduino_uno_vendor_id)){
                    arduino_is_available = true; //    arduino uno is available on this port
                    arduino_port_name = serialPortInfo.portName();
                    qDebug() << QString("Arduino Port Name: %1").arg(arduino_port_name);
                }
            }
        }
        /*
         *  Open and configure the arduino port if available
         */
        if(arduino_is_available){
            qDebug() << "Found the arduino port...\n";
            arduino->setPortName(arduino_port_name);
            arduino->setBaudRate(QSerialPort::Baud9600);
            arduino->setDataBits(QSerialPort::Data8);
            arduino->setFlowControl(QSerialPort::NoFlowControl);
            arduino->setParity(QSerialPort::NoParity);
            arduino->setStopBits(QSerialPort::OneStop);
            arduino->open(QSerialPort::ReadWrite);
            qDebug() << arduino->isOpen();
            QObject::connect(arduino, SIGNAL(readyRead()), this, SLOT(readSerial()));
            serialPortOpen();
        }else{
            serialPortEror();
        }
    
    }
    
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "arduinoserial.h"
    
    int main(int argc, char *argv[])
    {
        qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
    
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
    
        qmlRegisterType<ArduinoSerial>("arduino.serial", 1, 0, "ArduinoSerial");
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    
    

    main.qml

    import QtQuick 2.11
    import QtQuick.Window 2.11
    import QtQuick.VirtualKeyboard 2.3
    import QtQuick.Controls 2.2
    import arduino.serial 1.0
    import QtQuick.Dialogs 1.2
    
    Window {
        id: window
        visible: true
        width: 800
        height: 400
        title: qsTr("Serial Port")
    
        MessageDialog {
            id: serialErrorDialog
            title: "Serial Port Error"
            icon: "Critical"
            informativeText: "Can't find arduino!"
            standardButtons: StandardButton.Ok
            modality: Qt.ApplicationModal
            onAccepted: Qt.quit();
        }
    
        ArduinoSerial {
            id: typeFromArduinoSerial
    
            onSerialPortOpen: console.log("Serial Port Open")
    
            onSerialPortEror: serialErrorDialog.visible = true
    
            onDroValueChanged: lcdToUpdate.text = "DRO: " + droValue
    
        }
    
        Column{
            spacing: 50
    
            Row{
    
                Button {
                    id: serialstartbutton
                    text: "Open Serial Port"
                    onClicked: {
                        typeFromArduinoSerial.startSerialPort()
                        typeFromArduinoSerial.setLcdToUpdate(lcdupdate)
                    }
                }
    
                TextField {
                    id: lcdupdate
                    text: ""
                }
            }
    
                Row{
    
                    Button {
                        id: writeSerial1
                        text: "Write 20 to Serial"
                        onClicked: {
                            typeFromArduinoSerial.writeSerial("start 20 \r")
                            typeFromArduinoSerial.setLcdToUpdate(lcdupdate1)
                        }
                    }
    
                    TextField {
                        id: lcdupdate1
                        text: ""
                    }
                }
    
    
            Row {
    
                Button {
                    id: writeSerial2
                    text: "Write 50 to Serial"
                    onClicked: {
                        typeFromArduinoSerial.writeSerial("start 50 \r")
                    }
                }
    
                TextField {
                    id: lcdupdate2
                    text: ""
                }
            }
    
            Row{
                Button {
                    id: closeSerial
                    text: "Close Serial Port"
                    onClicked: {
                        typeFromArduinoSerial.closeSerialPort()
                    }
                }
            }
        }
    }
    
    
    

    Currently this runs but does not update any textfield?

    DiracsbracketD 1 Reply Last reply
    0
    • D Dave_022

      I am attempting to build on code that allows me to click a send button to send a value to Serial and then update the textfield associated with it with numbers returned. I can't work out how to control which text field is being updated without creating seperate instances for all of them?

      arduinoserial.h

      #include <QObject>
      #include <QSerialPort>
      
      class ArduinoSerial : public QObject
      {
          Q_OBJECT
          Q_PROPERTY(QString droValue READ droValue WRITE setDroValue NOTIFY droValueChanged)
          Q_PROPERTY(QString lcdToUpdate READ lcdToUpdate WRITE setLcdToUpdate NOTIFY lcdToUpdateChanged)
      
      public:
          ArduinoSerial();
          QString droValue() const;
          QString lcdToUpdate() const;
      
      public slots:    
          void startSerialPort(); // Starts the Open Serial Port Function
          void readSerial();
          void setDroValue(const QString& value);
          void closeSerialPort();
          void writeSerial(const QByteArray &data);
          void setLcdToUpdate(const QString &value);
      
      
      signals:
          void serialPortOpen(); // Signal for sucessfully opening Serial Port
          void serialPortEror(); // Signal on not finding arduino in openSerialPort
          void droValueChanged(); // Signal on data received from arduino
          void lcdToUpdateChanged(); // Signal on setting value for which lcd to use
      
      private:
          QSerialPort *arduino;
          static const quint16 arduino_uno_vendor_id = 9025;
          static const quint16 arduino_uno_product_id = 67;
          QString arduino_port_name;
          bool arduino_is_available;
          QString m_droValue;
          QString m_lcdToUpdate;
      
          void openSerialPort();
      };
      
      #endif // ARDUINOSERIAL_H
      
      

      arduinoserial.cpp

      #include "arduinoserial.h"
      #include <QDebug>
      #include <QSerialPort>
      #include <QSerialPortInfo>
      
      ArduinoSerial::ArduinoSerial()
      {   
      
      }
      
      QString ArduinoSerial::droValue() const
      {
          return m_droValue;
      }
      
      QString ArduinoSerial::lcdToUpdate() const
      {
          return m_lcdToUpdate;
          qDebug() << lcdToUpdate();
      }
      
      void ArduinoSerial::startSerialPort()
      {
          this->openSerialPort();
      }
      
      void ArduinoSerial::readSerial()
      {   
          // Read data
          static QByteArray byteArray;
          byteArray += arduino->readAll();
      
          //we want to read all message not only chunks
          if(!QString(byteArray).contains("\n"))
              return;
      
          //sanitize data
          QString data = QString( byteArray ).remove("\r").remove("\n");
          byteArray.clear();
      
          // Print data
          qDebug() << "RECV: " << data;
          setDroValue(data);
          droValueChanged();
      }
      
      void ArduinoSerial::setDroValue(const QString& value)
      {
          if (m_droValue != value) {
              m_droValue = value;
              droValueChanged();
          }
      }
      
      void ArduinoSerial::closeSerialPort()
      {
          if(arduino->isOpen()){
              arduino->close();
          }
          qDebug() << "Seriol Port is closed";
      }
      
      void ArduinoSerial::writeSerial(const QByteArray &data)
      {
         arduino->write(data);
         qDebug() << (data) + " written to serial";
      }
      
      void ArduinoSerial::setLcdToUpdate(const QString &value)
      {
          if(m_lcdToUpdate !=value) {
              m_lcdToUpdate = value;
              lcdToUpdateChanged();
              qDebug() << m_lcdToUpdate;
          }
      }
      
      void ArduinoSerial::openSerialPort()
      {
          /*
           *   Identify the port the arduino uno is on.
           */
          arduino = new QSerialPort;
          arduino_is_available = false;
          arduino_port_name = "";
      
          //
          //  For each available serial port
          foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()){
              //  check if the serialport has both a product identifier and a vendor identifier
              if(serialPortInfo.hasProductIdentifier() && serialPortInfo.hasVendorIdentifier()){
                  //  check if the product ID and the vendor ID match those of the arduino uno
                  if((serialPortInfo.productIdentifier() == arduino_uno_product_id)
                          && (serialPortInfo.vendorIdentifier() == arduino_uno_vendor_id)){
                      arduino_is_available = true; //    arduino uno is available on this port
                      arduino_port_name = serialPortInfo.portName();
                      qDebug() << QString("Arduino Port Name: %1").arg(arduino_port_name);
                  }
              }
          }
          /*
           *  Open and configure the arduino port if available
           */
          if(arduino_is_available){
              qDebug() << "Found the arduino port...\n";
              arduino->setPortName(arduino_port_name);
              arduino->setBaudRate(QSerialPort::Baud9600);
              arduino->setDataBits(QSerialPort::Data8);
              arduino->setFlowControl(QSerialPort::NoFlowControl);
              arduino->setParity(QSerialPort::NoParity);
              arduino->setStopBits(QSerialPort::OneStop);
              arduino->open(QSerialPort::ReadWrite);
              qDebug() << arduino->isOpen();
              QObject::connect(arduino, SIGNAL(readyRead()), this, SLOT(readSerial()));
              serialPortOpen();
          }else{
              serialPortEror();
          }
      
      }
      
      

      main.cpp

      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      #include <QQmlContext>
      #include "arduinoserial.h"
      
      int main(int argc, char *argv[])
      {
          qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
      
          QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
      
          QGuiApplication app(argc, argv);
      
          QQmlApplicationEngine engine;
      
          qmlRegisterType<ArduinoSerial>("arduino.serial", 1, 0, "ArduinoSerial");
      
          engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
          if (engine.rootObjects().isEmpty())
              return -1;
      
          return app.exec();
      }
      
      

      main.qml

      import QtQuick 2.11
      import QtQuick.Window 2.11
      import QtQuick.VirtualKeyboard 2.3
      import QtQuick.Controls 2.2
      import arduino.serial 1.0
      import QtQuick.Dialogs 1.2
      
      Window {
          id: window
          visible: true
          width: 800
          height: 400
          title: qsTr("Serial Port")
      
          MessageDialog {
              id: serialErrorDialog
              title: "Serial Port Error"
              icon: "Critical"
              informativeText: "Can't find arduino!"
              standardButtons: StandardButton.Ok
              modality: Qt.ApplicationModal
              onAccepted: Qt.quit();
          }
      
          ArduinoSerial {
              id: typeFromArduinoSerial
      
              onSerialPortOpen: console.log("Serial Port Open")
      
              onSerialPortEror: serialErrorDialog.visible = true
      
              onDroValueChanged: lcdToUpdate.text = "DRO: " + droValue
      
          }
      
          Column{
              spacing: 50
      
              Row{
      
                  Button {
                      id: serialstartbutton
                      text: "Open Serial Port"
                      onClicked: {
                          typeFromArduinoSerial.startSerialPort()
                          typeFromArduinoSerial.setLcdToUpdate(lcdupdate)
                      }
                  }
      
                  TextField {
                      id: lcdupdate
                      text: ""
                  }
              }
      
                  Row{
      
                      Button {
                          id: writeSerial1
                          text: "Write 20 to Serial"
                          onClicked: {
                              typeFromArduinoSerial.writeSerial("start 20 \r")
                              typeFromArduinoSerial.setLcdToUpdate(lcdupdate1)
                          }
                      }
      
                      TextField {
                          id: lcdupdate1
                          text: ""
                      }
                  }
      
      
              Row {
      
                  Button {
                      id: writeSerial2
                      text: "Write 50 to Serial"
                      onClicked: {
                          typeFromArduinoSerial.writeSerial("start 50 \r")
                      }
                  }
      
                  TextField {
                      id: lcdupdate2
                      text: ""
                  }
              }
      
              Row{
                  Button {
                      id: closeSerial
                      text: "Close Serial Port"
                      onClicked: {
                          typeFromArduinoSerial.closeSerialPort()
                      }
                  }
              }
          }
      }
      
      
      

      Currently this runs but does not update any textfield?

      DiracsbracketD Offline
      DiracsbracketD Offline
      Diracsbracket
      wrote on last edited by Diracsbracket
      #2

      @Dave_022 said in Variable to select textfield in QML:

      onDroValueChanged: lcdToUpdate.text = "DRO: " + droValue

      lcdToUpdate is not a QML TextField object. In fact, it is defined nowhere. If you think you are referring to the lcdToUpdate property of your ArduinoSerial type, then that wouldn't work either, because the property is a string.

      Furthermore,

      typeFromArduinoSerial.setLcdToUpdate(lcdupdate)

      lcdupdate is an id, while lcdToUpdate is a string property.

      When defining a custom QML type as you did, you are not supposed to access the properties with their setXXX function etc in QML: just do it as you would do with any other QML type:

      typeFromArduinoSerial.lcdToUpdate: myStringVar //when binding
      typeFromArduinoSerial.lcdToUpdate = myStringVar //when assigning in JS
      

      and vice versa.

      In your example you must use something like:

      typeFromArduinoSerial.lcdToUpdate = "LCD1"
      

      and

      onDroValueChanged: {
          if (lcdToUpdate ==="LCD1")
               lcdtoupdate1.text = "DRO: " + droValue
         else
               lcdtoupdate2.text = "DRO: " + droValue
      }
      

      or something like that.

      Finally, why don't you keep track of which LCD to update within QML only. This allows you to avoid having to define the lcdToUpdate property in your ArduinoSerial type whilst allowing you to do something like this:

      Window {
            property TextField lcdToUpdate: lcdtoupdate1 //default
      
            Button {
                          id: writeSerial1
                          text: "Write 20 to Serial"
                          onClicked: {
                              typeFromArduinoSerial.writeSerial("start 20 \r")
                              LcdToUpdate = lcdupdate1 //LcdToUpdate is essentially a reference to lcdupdate1 
                          }
                      }
      }
      

      Idem for the 2nd button.

      And then, you can use your original code:

      onDroValueChanged:  LcdToUpdate.text = "DRO: " + droValue
      
      1 Reply Last reply
      0
      • D Offline
        D Offline
        Dave_022
        wrote on last edited by
        #3

        Re: Variable to select textfield in QML

        /Finally, why don't you keep track of which LCD to update within QML only. This allows you to avoid having to define the lcdToUpdate property in your ArduinoSerial type whilst allowing you to do something like this:
        
        Window {
              property TextField lcdToUpdate: lcdtoupdate1 //default
        
              Button {
                            id: writeSerial1
                            text: "Write 20 to Serial"
                            onClicked: {
                                typeFromArduinoSerial.writeSerial("start 20 \r")
                                LcdToUpdate = lcdupdate1 //LcdToUpdate is essentially a reference to lcdupdate1 
                            }
                        }
        }
        Idem for the 2nd button.
        
        And then, you can use your original code:
        
        onDroValueChanged:  LcdToUpdate.text = "DRO: " + droValue
        

        Thank you; I attempted this myself prior to the code I posted and failed miserably. This has worked for me. Onwards and upwards...

        DiracsbracketD 1 Reply Last reply
        0
        • D Dave_022

          Re: Variable to select textfield in QML

          /Finally, why don't you keep track of which LCD to update within QML only. This allows you to avoid having to define the lcdToUpdate property in your ArduinoSerial type whilst allowing you to do something like this:
          
          Window {
                property TextField lcdToUpdate: lcdtoupdate1 //default
          
                Button {
                              id: writeSerial1
                              text: "Write 20 to Serial"
                              onClicked: {
                                  typeFromArduinoSerial.writeSerial("start 20 \r")
                                  LcdToUpdate = lcdupdate1 //LcdToUpdate is essentially a reference to lcdupdate1 
                              }
                          }
          }
          Idem for the 2nd button.
          
          And then, you can use your original code:
          
          onDroValueChanged:  LcdToUpdate.text = "DRO: " + droValue
          

          Thank you; I attempted this myself prior to the code I posted and failed miserably. This has worked for me. Onwards and upwards...

          DiracsbracketD Offline
          DiracsbracketD Offline
          Diracsbracket
          wrote on last edited by
          #4

          @Dave_022 said in Variable to select textfield in QML:

          This has worked for me. Onwards and upwards.

          Cheers!
          Also, don't forget to mark this post as solved...

          1 Reply Last reply
          1

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved