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.
-
@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. -
So what's the actual problem? Where did you stuck?
-
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.
-
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.
-
@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).
-
Hi
Ok.
Well looping over the table and getting the data and draw directly would be an optionfor (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?
-
@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.