keypressed and keyreleased
-
So my problem is quite simple, only the solution I don't see it.
I want when you press the "Z" key the robot will move forward. As long as you have not released the "Z" key, the robot should always move forward. Once you release the "Z" key the robot stops.
The debug console shows me:
Forward
keyReleased
Forward
keyReleased
Forward
keyReleased
What I would like it to display is as long as you press "Z" you get:
Forward
Forward
Forward
Then once we release "Z" we get:
keyReleased
I tried the timers and the autorepeat but they did not solve the problem -
@jeremy_k
void Robot::keyPressEvent(QKeyEvent*keyevent)
{
switch(keyevent->key())
{
case Qt:: Key_Z:
{Current_speed = ui->PWM_Curseur->value(); gpioPWM (12, 1600 + Current_speed); gpioPWM (13, 1600 + Current_speed); qDebug() << 1600 + Current_speed ; qDebug() << "Forward"; break; }
void Robot::keyReleaseEvent(QKeyEvent*keyevent)
{
if (keyevent->isAutoRepeat() == true)
{
keyevent->ignore();
}else { gpioPWM (12, 0); gpioPWM (13, 0); qDebug()<<"keyReleased"; }
}
-
@genli The console debug output does not match with the code you post... So it is hard to understand what really happens.
As side note: for me, the
QKeyEvent::isAutoRepeat()
only made sense inkeyPressEvent()
. In my comprehension, when autorepeate is set, then additional key pressed events are generated but no key released events. -
@KroMignon
The debug console shows me:
Forward
keyReleased
Forward
keyReleased
Forward
keyReleased
What I would like it to display is as long as you press "Z" you get:
Forward
Forward
Forward
Then once we release "Z" we get:
keyReleased -
@genli said in keypressed and keyreleased:
if (keyevent->isAutoRepeat() == true)
{
keyevent->ignore();
}
else {gpioPWM (12, 0);
gpioPWM (13, 0);qDebug()<<"keyReleased";
}
I think this sould be:
if(keyevent->key() == Qt::Key_Z) { if (keyevent->isAutoRepeat() == true) { keyevent->ignore(); qDebug()<<"release ignored"; } else { gpioPWM (12, 0); gpioPWM (13, 0); qDebug()<<"keyReleased"; } }
-
@genli
I actually answered a very similar question recently, can't find it any longer or I would have linked it, but I do still have the code example:#include <QKeyEvent> #include <QTimer> #include <QTime> class mWidget : public QWidget { Q_OBJECT public: explicit mWidget(QWidget * parent = nullptr) : QWidget(parent){ QObject::connect(&m_Timer, &QTimer::timeout, this, &mWidget::moveSlot); m_Timer.setInterval(20); } protected: QTimer m_Timer; virtual void keyPressEvent(QKeyEvent *event) override{ switch(event->key()) { case Qt:: Key_Z: { if(!m_Timer.isActive()){ m_Timer.start(); moveSlot(); }else qDebug() << "Key Z when timer running"; } default: qDebug() << "Other Key" << event->key(); } } virtual void keyReleaseEvent(QKeyEvent *event) override{ switch(event->key()) { case Qt:: Key_Z: { m_Timer.stop(); } default: qDebug() << "Other Key" << event->key(); } } private slots: void moveSlot(){ qDebug() << "Move" << QTime::currentTime(); } };
IIRC the idea was to send the command regularly through serial port or something. But the base idea of this should be the same, btw no autorepeat in this case!
-
@genli said in keypressed and keyreleased:
void Robot::keyReleaseEvent(QKeyEvent*keyevent)
{
if (keyevent->isAutoRepeat() == true)
{
keyevent->ignore();Why are you ignoring the event? From the documentation:
Clearing the accept parameter indicates that the event receiver does not want the event. Unwanted events might be propagated to the parent widget.
Based on the problem description, I don't think the goal is to have something else handle the autorepeated press and release events. The widget accepting the key press needs to accept autorepeats, and use the lack of autorepeat to signal the beginning and end of the physical key press.
-
@J-Hilk @KroMignon
thank you for your answer but it's still the same problem
my code with timers :
QObject::connect(&m_Timer, SIGNAL(timeout), this, SLOT(moveSlot));
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QObject::connect(&m_Timer, SIGNAL(timeout), this, SLOT(moveSlot));
m_Timer.setInterval(20);
}MainWindow::~MainWindow()
{
delete ui;
}void moveSlot()
{
qDebug() << "keyPressed";}
void MainWindow::keyPressEvent(QKeyEvent*keyevent)
{
switch(keyevent->key())
{
case Qt:: Key_Z:
{
if(!m_Timer.isActive()){
m_Timer.start();
moveSlot();} }
}
}void MainWindow::keyReleaseEvent(QKeyEvent*keyevent)
{switch(keyevent->key()) { case Qt:: Key_Z: { m_Timer.stop(); qDebug() << "keyReleased "; }
}
} -
@genli
Hi,
I suppose you have to manage more keys, not only Z.
A possible way to do this could be:- Having a timer always active where you could have all your managements ( like a core )
- In keyPressEvent(QKeyEvent*keyevent) store the key pressed
- In keyReleaseEvent(QKeyEvent*keyevent) clear the variable where you store key-value
Below there is an example of a body that is called from your timer
void MyObject::core()
{
...//Moving manager switch( keyPressed ) { case "Z": move1(); break; case "A": move2(); break; ... default: stopMoving(); break; } ...
}
You must check if this solution is compatible with your project design
-
@genli
Yes,
in my idea in keyReleaseEvent you must clear keyPressed variable (for example keyPressed=""), so in the switch the program skips in default and you stop all moving.It is clear that this logic could be improved to avoid doing the same operations
Is not key pressed but moving manager ;)
-
-
I changed the code but it's the same error :
void Robot::keyPressEvent(QKeyEvent*keyevent)
{
if (keyevent->key() == Qt::Key_Z)
{ui->forward_btn->pressed();
}
}
void Robot::keyReleaseEvent(QKeyEvent*keyevent)
{if (keyevent->key() == Qt::Key_Z) { ui->forward_btn->released(); }
}
any idea please ? -
@genli
The idea is having one place where manage the moving.
So my idea is the same:- having a timer always actived
- defining a enum or defines for direction
- in key event or pushbutton event store last moving selection.
Only for example:
enum Moving
{
enStop,
enForward,
enBack,
enLeft,
enRight
}Moving moving;
void MyObject::core()
{
...
//Moving managerswitch( moving)
{
case enForward:
move1();
break;case enBack: move2(); break; ... default: stopMoving(); break;
}
...
}void MyObject:: keyReleaseEvent(QKeyEventkeyevent)
{
keyPressed = enStop;
}
void MyObject::keyPressEvent(QKeyEventkeyevent)
{
if ( keyEvent->key() == "S" )
keyPressed = enForward;
else if ( keyEvent->key() == "D" )
keyPressed = enBack;
...
}//for all 4 buttons write a code like this
void MyObject::on_forward_btn_pressed()
{
keyPressed = enForward;
]void MyObject::on_forward_btn_relesed()
{
keyPressed = enStop;
]The above code could have error, I write in editor and not in QTCreator.
For security the stopOperation I insert always in default.
-
@CP71 the thing I can't understand is when I press Z:
The debug console shows me:
Forward
keyReleased
Forward
keyReleased
Forward
keyReleased
and when I keep pressing z and I press another button for example R or P the problem solved
The debug console shows me:
Forward
Forward
Forward
how i can press a button on the keyboard using code ?