QtWidgets to QtQuickControl2 c++



  • Hi to everyone,
    I have a project made with QWidget and with C++, but now I want to turn to QtQuickControl2... Someone knows how I have to do it? Thank you!!!



  • @patcs Have you separated the UI from the "business logic"? Are you going to still use the C++ for the logic and QML only for the UI, or are you going to use QML + javascript for everything?



  • @Eeli-K I would like continue with C++ for the logic and if it is possible not use any qml file. Only change the QWidgets to QtQuickControl.

    I dont know if I'm answering your questions. Sorry I'm a beginner.



  • @patcs If your project structure is already devided to UI and logic it will be much easier. Basically it should be so that the logic part is completely ignorant about the UI. It doesn't call the UI part in any way. It can be called by the UI and it sends signals to notify about changes. An easy to understand rule is that in the business logic files you don't #include any widget or other UI related headers. In the UI side you do only things which are directly related to showing things to the user and receiving input from the user. If you already have such an architecture, the change will be much easier. Then it will be about finding the proper Control2 elements, maybe redisigning the UI. But separating the logic in C++ is the first step. How far are you in that?



  • I dont know if I undestand well, For example I have this mainwindow.cpp file:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    #include "basedatosscreen.h"
    #include "QDataStream"
    #include <QTextEdit>
    #include <string>
    #include <QDesktopWidget>

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    qDebug()<<"Aplicación inicializada...";
    
    QString nombre_bd;
    nombre_bd.append("baseDeDatos1.sqlite");
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(nombre_bd);
    
    if(db.open()){
        qDebug()<<"Se ha conectado a la base de datos.";
    }else{
        qDebug()<<"ERROR! NO se ha conectado a la base de datos.";
    }
    
    createUserTable();
    ui->pushButtonAgregarUsuario->setToolTip("Agrega un usuario a la base de datos");
    ui->pushButtonBD->setToolTip("Accede a la base de datos");
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::createUserTable()
    {
    QString consulta;
    consulta.append("CREATE TABLE IF NOT EXISTS usuarios("
    "id INTEGER PRIMARY KEY AUTOINCREMENT,"
    "dni VARCHAR(100),"
    "nombre VARCHAR(100),"
    "apellido VARCHAR(100),"
    "apellido2 VARCHAR(100),"
    "edad INTEGER NOT NULL,"
    "notas VARCHAR(300),"
    "estres INTEGER NOT NULL,"
    "valoracion VARCHAR(20),"
    "duracion VARCHAR(20),"
    "elementos VARCHAR(30),"
    "fecha VARCHAR(20),"
    "hora VARCHAR(20)"
    ");");

    QSqlQuery crear;
    crear.prepare(consulta);
    
    if(crear.exec())
    {
        qDebug()<<"La tabla USUARIO existe o se ha creado correctamente.";
    
    }else{
        qDebug()<<"La tabla USUARIO NO se ha creado correctamente.";
        qDebug()<<"ERROR!"<<crear.lastError();
    
    }
    

    }
    QString valoracion_sesion = "" ;

    void MainWindow::insertUser()
    {
    QString dni_usuario = ui->lineEditDNI->text();
    QString nombre_usuario = ui->lineEditNombre->text();
    QString apellido_usuario = ui->lineEditPrimerApellido->text();
    QString apellido2_usuario = ui->lineEditSegundoApellido->text();
    QString edad_usuario = ui->lineEditEdad->text();
    QString notas_usuario = ui->textEdit->toPlainText();
    int estres_usuario = ui->horizontalSlider->value();
    QString fecha_sesion = ui->dateEdit->text();
    QString hora_sesion = ui->timeEdit->text();

    QString duracion_sesion = "";
    if(ui->radioButton->isChecked()){
        duracion_sesion = ui->radioButton->text();
    }else if(ui->radioButton_2->isChecked()){
        duracion_sesion = ui->radioButton_2->text();
    }else if(ui->radioButton_3->isChecked()){
        duracion_sesion = ui->radioButton_3->text();
    }
    
    QString elementos_sesion = "";
    if(ui->checkBox->isChecked() && ui->checkBox_2->isChecked() && ui->checkBox_3->isChecked()){
        elementos_sesion = "Luces, Colores, Sonidos";
    
    }else if(ui->checkBox->isChecked() && ui->checkBox_2->isChecked()){
        elementos_sesion = "Luces, Colores";
    
    }else if(ui->checkBox->isChecked() && ui->checkBox_3->isChecked()){
        elementos_sesion = "Luces, Sonidos";
    
    }else if(ui->checkBox_2->isChecked() && ui->checkBox_3->isChecked()){
        elementos_sesion = "Colores, Sonidos";
    
    }else if(ui->checkBox->isChecked()){
        elementos_sesion = "Luces";
    
    }else if(ui->checkBox_2->isChecked()){
        elementos_sesion = "Colores";
    
    }else if(ui->checkBox_3->isChecked()){
        elementos_sesion = "Sonidos";
    
    }
    
    
    
    
    
    QString consulta;
    
    consulta.append("INSERT INTO usuarios(id, dni, nombre, apellido, apellido2,edad, notas, estres, valoracion, duracion, elementos, fecha, hora)"
                        "values(:id, :dni, :nombre, :apellido, :apellido2, :edad , :notas, :estres , :valoracion, :duracion, :elementos, :fecha, :hora);");
    
    QSqlQuery insertar;
    insertar.prepare(consulta);
    
    insertar.bindValue(":dni", dni_usuario);
    insertar.bindValue(":nombre", nombre_usuario);
    insertar.bindValue(":apellido", apellido_usuario);
    insertar.bindValue(":apellido2", apellido2_usuario);
    insertar.bindValue(":edad", edad_usuario);
    insertar.bindValue(":notas", notas_usuario);
    insertar.bindValue(":estres", estres_usuario);
    insertar.bindValue(":valoracion", valoracion_sesion);
    insertar.bindValue(":duracion", duracion_sesion);
    insertar.bindValue(":elementos", elementos_sesion);
    insertar.bindValue(":fecha", fecha_sesion);
    insertar.bindValue(":hora", hora_sesion);
    
    
    if(insertar.exec())
    {
        qDebug()<<"El USUARIO se ha insertado correctamente.";
    
    }else{
        qDebug()<<"El USUARIO NO se ha insertado correctamente.";
        qDebug()<<"ERROR!"<<insertar.lastError();
    
    }
    

    }

    void MainWindow::on_pushButtonAgregarUsuario_clicked()
    {
    insertUser();
    BaseDatosScreen * dataShow1 = new BaseDatosScreen();
    dataShow1->dataShow();

    }

    void MainWindow::on_pushButtonBD_clicked()
    {
    BaseDatosScreen * MainWindow = new BaseDatosScreen();
    MainWindow->show();
    close();
    }
    void MainWindow::on_buenaVal_clicked()
    {

    valoracion_sesion = "Buena";
    

    }

    void MainWindow::on_normalVal_clicked()
    {

    valoracion_sesion = "Normal";
    

    }

    void MainWindow::on_malaVal_clicked()
    {

    valoracion_sesion = "Mala";
    

    }

    So you say that I have to delete the reference ui->?
    For example in this file that I should do exactly?



  • @patcs You said " if it is possible not use any qml file". That's not practically possible with Quick Controls. In an ideal case you have QML files for the UI but they don't have much executable code, they just declare the UI structure. In practice you have to write some javascript code, at least if you app is non-trivial (more than just one dialog or page). But if all the business logic is in C++ it's easier.



  • @patcs You should remove all the database related code from the mainwindow and create a class which handles it. The main window will be replaced with a QML file (or files). The QML code receives data from the C++ class using for example models inherited from QAbstactItemModel and simple QStrings. Read http://doc.qt.io/qt-5/qtqml-cppintegration-topic.html.

    I think you should first rewrite your architecture so that the UI and the logic are really separated. But it's very difficult to help with that without seeing face to face, and I don't of course have time for that anyways. Try to find resources on software architecture (maybe someone here could recommend some?).

    It will be difficult at first but one very good upside of C++ logic/QML UI distinction is that you are forced to understand that separation better and your understanding and coding habits will be only better because of that.



  • thank you for everything i'm going to try!



  • Hi, again @Eeli-K
    I was trying that you say me but I had a lot of problems... maybe if you have time you can help me... and say me specifically how to do it.

    I have 2 C++ classes:

    basedatosscreen.cpp file:
    #include "basedatosscreen.h"
    #include "ui_basedatosscreen.h"
    #include "mainwindow.h"
    #include <QDebug>
    #include <QMessageBox>

    BaseDatosScreen::BaseDatosScreen(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::BaseDatosScreen)
    {
    ui->setupUi(this);
    dataShow();
    f = -1;

    ui->pushButton_BSeleccion->setToolTip("Borrar usuario");
    ui->pushButton->setToolTip("Vuelve a la página de insertar usuario");
    

    }

    BaseDatosScreen::~BaseDatosScreen()
    {
    delete ui;
    }

    void BaseDatosScreen::dataShow()
    {
    QString consultation;
    consultation.append("SELECT id, dni, nombre, apellido, apellido2,edad, notas, estres, valoracion, duracion, elementos, fecha, hora FROM usuarios");
    QSqlQuery consultar;
    consultar.prepare(consultation);

    if(consultar.exec())
    {
        qDebug()<<"Se ha consultado correctamente.";
    
    }else{
        qDebug()<<"NO se ha consultado correctamente.";
        qDebug()<<"ERROR!"<<consultar.lastError();
    
    }
    
    
    int fila = 0;
    ui->dataTable->setRowCount(0);
    
    while(consultar.next()){
    
        ui->dataTable->insertRow(fila);
        ui->dataTable->setItem(fila, 0, new QTableWidgetItem(QString::number(consultar.value(0).toInt())));
        ui->dataTable->setColumnHidden(0,true);
        ui->dataTable->setItem(fila, 1, new QTableWidgetItem(consultar.value(1).toByteArray().constData()));
        ui->dataTable->setItem(fila, 2, new QTableWidgetItem(consultar.value(2).toByteArray().constData()));
        ui->dataTable->setItem(fila, 3, new QTableWidgetItem(consultar.value(3).toByteArray().constData()));
        ui->dataTable->setItem(fila, 4, new QTableWidgetItem(consultar.value(4).toByteArray().constData()));
        ui->dataTable->setItem(fila, 5, new QTableWidgetItem(consultar.value(5).toByteArray().constData()));
        ui->dataTable->setItem(fila, 6, new QTableWidgetItem(consultar.value(6).toByteArray().constData()));
        ui->dataTable->setItem(fila, 7, new QTableWidgetItem(consultar.value(7).toByteArray().constData()));
        ui->dataTable->setItem(fila, 8, new QTableWidgetItem(consultar.value(8).toByteArray().constData()));
        ui->dataTable->setItem(fila, 9, new QTableWidgetItem(consultar.value(9).toByteArray().constData()));
        ui->dataTable->setItem(fila, 10, new QTableWidgetItem(consultar.value(10).toByteArray().constData()));
        ui->dataTable->setItem(fila, 11, new QTableWidgetItem(consultar.value(11).toByteArray().constData()));
        ui->dataTable->setItem(fila, 12, new QTableWidgetItem(consultar.value(12).toByteArray().constData()));
    
        fila++;
    
    }
    

    }

    void BaseDatosScreen::on_pushButton_clicked()
    {
    MainWindow * BaseDatosScreen = new MainWindow();
    BaseDatosScreen->show();
    close();

    }

    void BaseDatosScreen::on_pushButton_BSeleccion_clicked()
    {

    QMessageBox::StandardButton reply;
    reply= QMessageBox::question(this,tr("Borrar"),tr("¿Está seguro de que quiere eliminar la sesión?"),QMessageBox::Yes | QMessageBox::No);
    
    
    
    if(reply == QMessageBox::Yes){
        int rownum = ui->dataTable->row(ui->dataTable->selectedItems().at(0));
        int id = ui->dataTable->item(rownum, 0)->data(0).toInt();
        QSqlQuery query;
        query.prepare("DELETE FROM usuarios WHERE id = ?");
        query.addBindValue(id);
        ui->dataTable->removeRow(rownum);
    
    
    
        if(query.exec())
        {
            qDebug()<<"Se ha borrado correctamente.";
    
        }else{
            qDebug()<<"NO se ha borrado correctamente.";
            qDebug()<<"ERROR!"<<query.lastError();
    
        }
    
    }
    

    }

    mainwindow.cpp file:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QDebug>
    #include "basedatosscreen.h"
    #include "QDataStream"
    #include <QTextEdit>
    #include <string>
    #include <QDesktopWidget>

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    qDebug()<<"Aplicación inicializada...";
    
    QString nombre_bd;
    nombre_bd.append("baseDeDatos1.sqlite");
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(nombre_bd);
    
    if(db.open()){
        qDebug()<<"Se ha conectado a la base de datos.";
    }else{
        qDebug()<<"ERROR! NO se ha conectado a la base de datos.";
    }
    
    createUserTable();
    ui->pushButtonAgregarUsuario->setToolTip("Agrega un usuario a la base de datos");
    ui->pushButtonBD->setToolTip("Accede a la base de datos");
    

    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }

    void MainWindow::createUserTable()
    {
    QString consulta;
    consulta.append("CREATE TABLE IF NOT EXISTS usuarios("
    "id INTEGER PRIMARY KEY AUTOINCREMENT,"
    "dni VARCHAR(100),"
    "nombre VARCHAR(100),"
    "apellido VARCHAR(100),"
    "apellido2 VARCHAR(100),"
    "edad INTEGER NOT NULL,"
    "notas VARCHAR(300),"
    "estres INTEGER NOT NULL,"
    "valoracion VARCHAR(20),"
    "duracion VARCHAR(20),"
    "elementos VARCHAR(30),"
    "fecha VARCHAR(20),"
    "hora VARCHAR(20)"
    ");");

    QSqlQuery crear;
    crear.prepare(consulta);
    
    if(crear.exec())
    {
        qDebug()<<"La tabla USUARIO existe o se ha creado correctamente.";
    
    }else{
        qDebug()<<"La tabla USUARIO NO se ha creado correctamente.";
        qDebug()<<"ERROR!"<<crear.lastError();
    
    }
    

    }
    QString valoracion_sesion = "" ;

    void MainWindow::insertUser()
    {
    QString dni_usuario = ui->lineEditDNI->text();
    QString nombre_usuario = ui->lineEditNombre->text();
    QString apellido_usuario = ui->lineEditPrimerApellido->text();
    QString apellido2_usuario = ui->lineEditSegundoApellido->text();
    QString edad_usuario = ui->lineEditEdad->text();
    QString notas_usuario = ui->textEdit->toPlainText();
    int estres_usuario = ui->horizontalSlider->value();
    QString fecha_sesion = ui->dateEdit->text();
    QString hora_sesion = ui->timeEdit->text();

    QString duracion_sesion = "";
    if(ui->radioButton->isChecked()){
        duracion_sesion = ui->radioButton->text();
    }else if(ui->radioButton_2->isChecked()){
        duracion_sesion = ui->radioButton_2->text();
    }else if(ui->radioButton_3->isChecked()){
        duracion_sesion = ui->radioButton_3->text();
    }
    
    QString elementos_sesion = "";
    if(ui->checkBox->isChecked() && ui->checkBox_2->isChecked() && ui->checkBox_3->isChecked()){
        elementos_sesion = "Luces, Colores, Sonidos";
    
    }else if(ui->checkBox->isChecked() && ui->checkBox_2->isChecked()){
        elementos_sesion = "Luces, Colores";
    
    }else if(ui->checkBox->isChecked() && ui->checkBox_3->isChecked()){
        elementos_sesion = "Luces, Sonidos";
    
    }else if(ui->checkBox_2->isChecked() && ui->checkBox_3->isChecked()){
        elementos_sesion = "Colores, Sonidos";
    
    }else if(ui->checkBox->isChecked()){
        elementos_sesion = "Luces";
    
    }else if(ui->checkBox_2->isChecked()){
        elementos_sesion = "Colores";
    
    }else if(ui->checkBox_3->isChecked()){
        elementos_sesion = "Sonidos";
    
    }
    
    
    
    
    
    QString consulta;
    
    consulta.append("INSERT INTO usuarios(id, dni, nombre, apellido, apellido2,edad, notas, estres, valoracion, duracion, elementos, fecha, hora)"
                        "values(:id, :dni, :nombre, :apellido, :apellido2, :edad , :notas, :estres , :valoracion, :duracion, :elementos, :fecha, :hora);");
    
    QSqlQuery insertar;
    insertar.prepare(consulta);
    
    insertar.bindValue(":dni", dni_usuario);
    insertar.bindValue(":nombre", nombre_usuario);
    insertar.bindValue(":apellido", apellido_usuario);
    insertar.bindValue(":apellido2", apellido2_usuario);
    insertar.bindValue(":edad", edad_usuario);
    insertar.bindValue(":notas", notas_usuario);
    insertar.bindValue(":estres", estres_usuario);
    insertar.bindValue(":valoracion", valoracion_sesion);
    insertar.bindValue(":duracion", duracion_sesion);
    insertar.bindValue(":elementos", elementos_sesion);
    insertar.bindValue(":fecha", fecha_sesion);
    insertar.bindValue(":hora", hora_sesion);
    
    
    if(insertar.exec())
    {
        qDebug()<<"El USUARIO se ha insertado correctamente.";
    
    }else{
        qDebug()<<"El USUARIO NO se ha insertado correctamente.";
        qDebug()<<"ERROR!"<<insertar.lastError();
    
    }
    

    }

    void MainWindow::on_pushButtonAgregarUsuario_clicked()
    {
    insertUser();
    BaseDatosScreen * dataShow1 = new BaseDatosScreen();
    dataShow1->dataShow();

    }

    void MainWindow::on_pushButtonBD_clicked()
    {
    BaseDatosScreen * MainWindow = new BaseDatosScreen();
    MainWindow->show();
    close();
    }
    void MainWindow::on_buenaVal_clicked()
    {

    valoracion_sesion = "Buena";
    

    }

    void MainWindow::on_normalVal_clicked()
    {

    valoracion_sesion = "Normal";
    

    }

    void MainWindow::on_malaVal_clicked()
    {

    valoracion_sesion = "Mala";
    

    }

    I wish you can help me.. Thanks in advance.



  • @patcs Now you have two UI classes (window or screen). You should have only user interface element related code in those and simple calls to a backend. Move away all code which has something like "QSqlQuery", SQL query strings (INSERT, DELETE etc. etc.) or anything which is not statically in the user interface. Usually the button texts, UI labels etc. belong to the user interface. But the data, the thing you actually want to use with application, belongs to a backend (or to an engine or business logic). Think like this: I want to write a completely new user interface for this data, maybe even with another widget library. What can I still keep? Or vice versa: I want to keep this user interface but handle the data completely differently, for example with simple files instead of SQL database; I will move the data handling to a new class; after that my UI files won't change even when I change the data handling code.

    So, move all the database handling to a new class and hide the implementation details behind an API. Write simple public functions which use strings, don't move SQL classes or commands between the UI and the backend. Or even better: the recommended technique in Qt for data and UI separation is the Model/View architecture. At first it takes time to learn it but you should learn it anyways if you want to write more Qt software than just this one. Start with http://doc.qt.io/qt-5/model-view-programming.html.


Log in to reply
 

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