Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Reading rows from qtableview and using them to draw in new window



  • Hello, I need little bit of help. I'm trying to draw a simple map of a grid based maze, but I got stuck at the start of my project. I loaded the data about the maze (coordinates of individual squares, position of the obstacles and orientation of a robot moving through the maze) from database to QTableView. From this tableview I would like to read values from individual rows and then by clicking on button draw in new window lines accordingly to the obstacles.


  • Lifetime Qt Champion

    @thalorn said in Reading rows from qtableview and using them to draw in new window:

    I don't know if its possible, but can I just call the paintEvent function in every if condition?

    You can always call update() to have it redraw.

    You only have one QLine object so while you do loop the rows, the QLine object will just be moved around since only
    one exists.
    So when the paintEvent is called, only the last values you assigned are drawn.

    If you need to have multiple lines then
    Qvector<QLine> lines;
    or similar will be need so all lines is stored and not just the last processed.
    You just then loop the vector and draw each QLine in paintEvent.


  • Qt Champions 2019

    So what's the actual problem? Where did you stuck?



  • Geez I'm bad at asking questions in english. Anyway I don't know how to load whole row from tableview and if it's worth to save the rows values into a array or vector and then to work with them or just load them to separate variables.


  • Qt Champions 2019

    You should read Qt Model View page. Then you'll understand that each view needs a model where the data is stored. And retrieving the data from the model afterwards is not that hard.


  • Lifetime Qt Champion

    Hi
    Is it some sort of maze editor ?
    Depending on how you want to work with the data, it might be easier to load the data to a structure that represents a Maze more closely than a set of rows.

    What model are you using with the view ?
    The model holds the data and normally you would use the data from the model directly and not via the view but it is of course also an option.

    However, if you tell a bit more about the data and how you need to process it to draw the lines and what else needs to be done then we can suggest better.



  • It should be just an app that draws map of a maze which my arduino robot goes through. He send data like this: x:0 y:0 obstacle left:1 (if value is 1 then there is obstacle) obstacle right:1 obstacle front: 0 obstacle back: 1 direction of a robot: 1-4 (1 is up, 2 right, 3 down and 4 is left). I'm using QuerryModel

    void loadDB::on_pb_Load_clicked()
    {
        db = QSqlDatabase::addDatabase("QMYSQL");
        db.setHostName("127.0.0.1");
        db.setDatabaseName("arduino");
        db.setUserName("root");
        db.setPassword("");
        if(db.open())
        {
            QMessageBox::information(this, "Connected", "Connected");
            qry = new QSqlQueryModel();
            qry->setQuery("SELECT * FROM data");
            ui->tableView->setModel(qry);
        }
        else
        {
            QMessageBox::critical(this, "Error", db.lastError().text());
            return;
        }
    }
    

    My idea was that if I know the dimensions of the maze which is on grid, I can say that 1 square in drawing has 50px so I could just draw a line long 50px according to values in obstacle columns.


  • Lifetime Qt Champion

    @thalorn
    Hi
    If you read
    https://doc.qt.io/qt-5/qsqlquerymodel.html#details
    you can see how to access the without using a view.

        QSqlTableModel model;
        model.setTable("employee");
        model.select();
        int salary = model.record(4).value("salary").toInt(); // row 4, salary col.
    

    I think that will work fine for reading and using the data. Im not sure what one row of data represents.
    Do you need all the rows to define all of the maze or will one row at the time be good enough ?

    I assume you have much other data than the maze since you are using a MySqlServer ?
    Or are you using it as a way to send data from the arduino ?



  • Im using MySqlServer because it was assignment from school and it was easy way to send data from arduino. I need all the rows to dral whole maze and one row looks like this: id:1, x:0, y:0, obstacle left:1 (if value is 1 then there is obstacle), obstacle right:1, obstacle front: 0, obstacle back: 1, direction of a robot: 1-4 (where 1 is up, 2 right, 3 down and 4 is left).


  • Lifetime Qt Champion

    Hi
    Ok.
    Well looping over the table and getting the data and draw directly would be an option

    for (int row = 0; row < model.rowCount(); ++row) {
            int xxx = model.record(row).value("xxx").toInt();
            int yyy = model.record(row).value("yyy").toInt();
            DrawIt( xxx, yyy, ...);
        }
    

    However, it sounds like you need to draw the maze over and over to show the moving robot etc so
    i think i would store the data in a simple strcuture to allow to draw it easy without having to loop the
    database each time.



  • Hi,
    I think I made some progress. I just need to draw it. I tried it this way, but I can only draw the first line.

    loaddb.h

    #ifndef LOADDB_H
    #define LOADDB_H
    
    #include <QMainWindow>
    #include <QtSql>
    #include <QSqlDatabase>
    #include <QSqlTableModel>
    #include <QSqlError>
    #include <QMessageBox>
    #include <QPainter>
    
    namespace Ui {
    class loadDB;
    }
    
    class loadDB : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit loadDB(QWidget *parent = nullptr);
        ~loadDB();
        virtual void paintEvent(QPaintEvent *event);
    
    private slots:
        void on_pb_Load_clicked();
    
    private:
        Ui::loadDB *ui;
        QSqlQueryModel *qry;
        QSqlDatabase db;
        QLine line;
        QPoint p1;
        QPoint p2;
        QPoint p3;
        QPoint p4;
        int x;
        int y;
        int direction;
        int left;
        int right;
        int front;
        int back;
        int x_s= 0;     // x start
        int y_s= 150;   // y start
        int x_f= 0;     // x finish
        int y_f= 100;   // y finish
        bool draw;
    };
    
    #endif // LOADDB_H
    

    loaddb.cpp

    #include "loaddb.h"
    #include "ui_loaddb.h"
    
    loadDB::loadDB(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::loadDB)
    {
        ui->setupUi(this);
    
    }
    
    loadDB::~loadDB()
    {
        db.close();
        delete ui;
    }
    
    void loadDB::paintEvent(QPaintEvent *event)
    {
        QPainter painter(this);
        QPen pen;
        pen.setWidth(3);
        painter.setPen(pen);
        painter.drawLine(line);
        update();
    }
    
    
    void loadDB::on_pb_Load_clicked()
    {
    
        //db columns
        int db_x = 1;
        int db_y = 2;
        int db_left = 6;
        int db_right = 4;
        int db_front = 3;
        int db_back = 5;
        int db_direction = 7;
    
    
    
        db = QSqlDatabase::addDatabase("QMYSQL");
        db.setHostName("127.0.0.1");
        db.setDatabaseName("arduino");
        db.setUserName("root");
        db.setPassword("");
        if(db.open())
        {
            QMessageBox::information(this, "Connected", "Connected");
            qry = new QSqlQueryModel();
            qry->setQuery("SELECT * FROM data");
            for (int row = 0; row < qry->rowCount(); ++row)
            {
                x = qry->record(row).value(db_x).toInt();
                y = qry->record(row).value(db_y).toInt();
                direction = qry->record(row).value(db_direction).toInt();
                left = qry->record(row).value(db_left).toInt();
                right = qry->record(row).value(db_right).toInt();
                front = qry->record(row).value(db_front).toInt();
                back = qry->record(row).value(db_back).toInt();
                switch (direction) {
                case 1:
                    y_s = y_s - (y*50);
                    y_f = y_f - (y*50);
                    // left
                    p1.setX(x_s);
                    p1.setY(y_s);
    
                    p4.setX(x_s);
                    p4.setY(y_f);
                    //right
                    p2.setX(x_f);
                    p2.setY(y_s);
    
                    p3.setX(x_f);
                    p3.setX(y_f);
    
                    if (left == 1){
                        line.setP1(p1);
                        line.setP2(p4);
                        
                    }
                    if (right == 1){
                        line.setP1(p2);
                        line.setP2(p3);
                        
                    }
                    if(front == 1) {
                        line.setP1(p3);
                        line.setP2(p4);
                        
                    }
                    if(back == 1){
                        line.setP1(p1);
                        line.setP2(p2);
                        
                    }
                    break;
                case 2:
                    x_s = x * 50;
                    x_f = x_s + 50;
    
                    // right
                    p1.setX(x_s);
                    p1.setY(y_s);
    
                    p2.setX(x_f);
                    p2.setY(y_s);
    
                    // left
                    p3.setX(x_f);
                    p3.setY(y_f);
    
                    p4.setX(x_s);
                    p4.setY(y_f);
                    if (left == 1){
                        line.setP1(p3);
                        line.setP2(p4);
                        
                    }
                    if (right == 1){
                        line.setP1(p1);
                        line.setP2(p2);
                        
                    }
                    if(front == 1) {
                        line.setP1(p2);
                        line.setP2(p3);
                        
                    }
                    if(back == 1){
                        line.setP1(p1);
                        line.setP2(p4);
                        
                    }
                    break;
                case 3:
                    y_s = y_s - (y*50);
                    y_f = y_f - (y*50);
                    //left
                    p1.setX(x_s);
                    p1.setY(y_s);
    
                    p4.setX(x_s);
                    p4.setY(y_f);
                    //right
                    p2.setX(x_f);
                    p2.setY(y_s);
    
                    p3.setX(x_f);
                    p3.setX(y_f);
    
    
                    if (left == 1){
                        line.setP1(p1);
                        line.setP2(p4);
                       
                    }
                    if (right == 1){
                        line.setP1(p2);
                        line.setP2(p3);
                       
                    }
                    if(front == 1) {
                        line.setP1(p1);
                        line.setP2(p2);
                       
                    }
                    if(back == 1){
                        line.setP1(p4);
                        line.setP2(p3);
                        
                    }
                    break;
                case 4:
                    x_s = x * 50;
                    x_f = x_s + 50;
    
                    // left
                    p1.setX(x_s);
                    p1.setY(y_s);
    
                    p2.setX(x_f);
                    p2.setY(y_s);
    
                    // right
                    p3.setX(x_f);
                    p3.setY(y_f);
    
                    p4.setX(x_s);
                    p4.setY(y_f);
                    if (left == 1){
                        line.setP1(p1);
                        line.setP2(p2);
                        
                    }
                    if (right == 1){
                        line.setP1(p4);
                        line.setP2(p2);
                        
                    }
                    if(front == 1) {
                        line.setP1(p1);
                        line.setP2(p4);
                        
                    }
                    if(back == 1){
                        line.setP1(p2);
                        line.setP2(p3);
                        
                    }
    
                    break;
                default:
                    break;
                }
            }
    
    
        }
        else
        {
            QMessageBox::critical(this, "Error", db.lastError().text());
            return;
        }
    
    }
    

    I don't know if its possible, but can I just call the paintEvent function in every if condition?


  • Lifetime Qt Champion

    @thalorn said in Reading rows from qtableview and using them to draw in new window:

    I don't know if its possible, but can I just call the paintEvent function in every if condition?

    You can always call update() to have it redraw.

    You only have one QLine object so while you do loop the rows, the QLine object will just be moved around since only
    one exists.
    So when the paintEvent is called, only the last values you assigned are drawn.

    If you need to have multiple lines then
    Qvector<QLine> lines;
    or similar will be need so all lines is stored and not just the last processed.
    You just then loop the vector and draw each QLine in paintEvent.



  • Thank you very much, I managed to finally do it.


Log in to reply