PDA

View Full Version : Need help handling received messages with QWebSocket based GUI



JaffaMicrobrain
25th August 2015, 12:43
AIM
I am writing a Qt GUI client that interacts with a database server via firewall friendly network traffic. In testing this I have created a trivial GUI project opening connections to Qt EchoServer. On button-click I can send a string to EchoServer. What I really want is to allow the user to enter an ID into a Line Edit box, then for my code to send this ID to the server which replies with a string. This string to then be placed into a Line Edit box (or Label) adjacent to the ID Line Edit. Then to move on to the next Line Edit box and so on. The proper application will be doing database lookups - but I am OK with that.

PROBLEM
I am stuck on how to handle the reply from the server and how to place it into the correct widget on my form.

MY ATTEMPTS
I have tried creating WebSocket in my MainWindow code module and then connecting QWebSocket::textMessageReceived to one of a number of handlers. I have also tried implementing my WebSocket as a thread and waiting for completion before fetching the reply from the WebSocket thread and stuffing the result into my form. Neither of these approaches seem elegant.

What is the way to do this please? Can anyone explain or provide a link to a web tutorial?

I am fairly new to Qt and returning to C++ after 10 years of other work (Embedded C, Java, etc)

Frdz
25th August 2015, 16:59
Ouchh,, my compilers getting confused at line 4 near "placed into Line Edit box" :D
Well have you tried qt network project example? what kind of feature you want to add more?

Added after 37 minutes:

Ok, I'm pretending know your problem. Please correct me if i have wrong asumption

1. Rather than using many QLineEdit/QLabel and move the received data between them, better use 2 QLineEdit for UserID & message, and 1 QPlainTextEdit (or even better QTextEdit/QTextBrowser in case you need special coloring) for received message,just like console view/log view. Use "QTextEdit::moveCursor(QTextCursor::Start)" before writing new line
2. Before sending message to server, you can add the message with UserID using QString append/prepend and separator that has known by server
3. Parse the message+UserID in server side, execute parsed message to DB, then return the values to client like in echo client-server example

JaffaMicrobrain
25th August 2015, 18:11
I really thought I had explained my problem clearly. Evidently this is not the case... Sorry!

Here we are talking about a GUI in which my user must enter key data, which is validated against a database and the confirmation displayed in the GUI next to the key data input. For example; entering EmployeeID results in my code passing the ID back to the server, then getting the Employee Name back as a string which I then display in the Employee Name box. Whatever widget is chosen for the box. I anticipate this message passing and reply getting being done by JSON via WebSockets. I am OK with database, JSON and the like.

After EmployeeID is done I can then change focus, or enable the next widget to handle the next item of data. Say, ItemID and ItemName, then BuildingID and BuildingName, etc.

I don't mean to be vague. I wish to avoid your time being spent explaining stuff that I am not stuck on. What is the best practice to handle sends and replies via QWebSockets in a GUI form? Eg: Send key data to the server and then display the result for a number of sequential inputs.

Thank you.

Frdz
25th August 2015, 21:30
Eheh, I'm so sorry for my misunderstanding
Modifying my prev project, hope can give you a little clue



class MyClient;

private slots:
void sendMsg();
void receiveMsg();

private:
Ui::MyClient *ui;
QLineEdit* activeLineEdit;
QLabel* activeLabel;




#include "myclient.h"
#include "ui_myclient.h"
#include <QDebug>

MyClient::MyClient(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MyClient)
{
ui->setupUi(this);
foreach (QWidget *widget, findChildren<QWidget *>()) //hide all lineedit & label
widget->setVisible(false);
foreach (QLabel *label, findChildren<QLabel *>()) //make label read only to display received data
label->setEnabled(false);
foreach (QLineEdit *lineedit, findChildren<QLineEdit *>()) //create connect signal & slot
connect(lineedit, SIGNAL(editingFinished()), this, SLOT(sendMsg()));
ui->lineEdit_1->setVisible(true); //show the first entry field
ui->label_1->setVisible(true);
connect(&m_webSocket, &QWebSocket::textMessageReceived, this, receivedMsg);
}

void MyClient::sendMsg()
{
activeLineEdit = qobject_cast<QLineEdit*>(sender());
qDebug()<<activeLineEdit->text(); //just to check the line edit value
//send the value to server, add header as you need e.g requested objectindex
//objectindex related to enumerator of table/column in your db against existing qlabel
}

void MyClient::receiveMsg()
{
bool validity;
//suppose you get data from server e.g (validity~objectindex~receivedmessage)
//parse received message
if (!validity)
{
//re-entry or something
}
else
{
QString testName = QString("label_%1").arg(objectindex);
QString testName2 = QString("label_%1").arg(objectindex+1);
foreach (QLabel *whichlabel, findChildren<QLabel *>())
{
if (whichlabel->objectName()==testName) //lookup right label to place the message
whichlabel->setText(receivedMessage);
if (whichlabel->objectName()==testName2) //show next label
whichlabel->setVisible(true);
}
activeLineEdit->nextInFocusChain()->setVisible(true);//show next field
activeLineEdit->nextInFocusChain()->setFocus();
}
}

...all the rest is about qwebsocket connection & data processing in server I think you could manage it.
For the last part, maybe any expert here have better approach. My method above rely on ordered QObject naming.
I'v ever seen wysota in different thread using static meta object enumeration, may be can be used to move to next item. Have it try

JaffaMicrobrain
26th August 2015, 10:51
Thank you Frdz.

Of course I would be using message ID's for the server to identify the service request. Funny - it did not occur to me to pass back a reply ID that could be used within the GUI to place the data into the correct widget. Thank you for pointing that out.

The big question now is...

Should I run the QWebSocket instance in it's own thread?

Again, thank you.

Frdz
26th August 2015, 17:22
Ah, it's up to you. Actually implementation of basic qwebsocket is simple in Qt.
In my opinion it's depend on how complex your app next expansion, maybe you face security issues or something next day so you need to run it separately to make you ease. Good luck
^^