Replace STDIN with a Serial port
-
You should rather write a little class that represent that keypad and have the QSerialPort in there. You'll connect that class to your GUI to keep things cleanly separated.
On a side note, QWidget is a QObject so there's no need to cast. Furthermore, never use c style cast with QObject derived class, use qobject_cast.
-
-
What i'm missing is: should I create a new thread for it to monitor the serial port and create the events? or not?
-
In this case I normally use an Object based on QThread to manage the serial device. I normally add to the object the Tcp features, because sometimes the serial device can be attached with a rs232 - tct converter.
The object has to manage the device and can emit an event at particular situations.
For example, if you have a usb - rfid reader, when a tag will read, the object emit an event with the read tag code. -
So it has to be something like this:
@
class Keypad : public Qthread {public: Keypad(){ initialize_serial_port(); this->start();
}
private: QSerialPort serial; void run() { while(1) { serial.get_stff(); generate_event_for_gui(); }
}
};@ -
Technically, threads are not mandatory at all in this case unless you start heavy processing on the data you received.
-
But I don't see where and how to create a loop for the events in the GUI.
-
You already have an event loop after you call app.exec(). Use QSerialPort in asynchronous mode
-
but how do I get in that loop!?! That's what I don't get
-
You don't need to get in that loop, once app.exec is called, the loop runs. Events are sent, signals and slots activates when needed etc.
-
Yeah.. that's what I'm trying to do now. Since I can't use the serial port in a separated thread.
So what now? Do I have to create a signal handler for the serial?
I'm quite new to GUIs writing, I'm mainly a microcontroller programmer. Sorry if this are really n00b questions. -
I never said it won't work in a separated thread, just that it's really not needed.
Something like this:
@
class KeyPad :: public QObject {
Q_OBJECT
public:
KeyPad(QObject *parent = 0 ) :
QObject(parent)
{
connect(&serialPort, SIGNAL(readyRead()), SLOT(processData()));
}bool initialize(const QString &portName)
{
serialPort.setPortName(portName);
// setup portreturn serialPort.open(QIODevice::ReadWrite); // or ReadOnly if you won't write anything in it
}
signals:
valueChanged(int newValue);private slots:
void processData() {
data.append(serialPort.readAll());
// check if enough data is there
// parse data
// removed processed data from buffer
// emit signal(s)
}private:
QByteArray data;
QSerialPort serialPort;
};
@I've wrote everything in the "header" for brevity only
-
@ connect(&serialPort, SIGNAL(readyRead()), SLOT(processData()));@
I get it now, I was doing right that as you write! SO that's what gets it in the "main event loop" right?
Of course you didn't said it won't work in a separated thread, but I tried just that and it didn't work because of some "can't create new thread issue"
THANKS A LOT!!
-
So I got it, now I can navigate the menues with the serial port as I did with the keyboard. But the only thing that's not working are text entries. Whenever I need to input some text in a QLineEdit widget it doesn't recognizes the input as a keystroke!
@
void Keypad::SerialPortHandler (void){
char buff;serial->read(&buff,1);
QKeyEvent *last_key = new QKeyEvent( QEvent::KeyPress, buff , Qt::GroupSwitchModifier, QString(buff) );
QCoreApplication::sendEvent(pycgui,last_key);
}
@I use Qt::GroupSwitchModifier only to differentiate the events I create from the real one so I can manually delete them. But it's not the reason the input is not working!
-
AFAIK, text input requires a press and a release event