keyPressEvent(QKeyEvent *e) does not work for enter key - c++

I am trying to detect when a user presses Enter or Alt+Enter in a QTextEdit. I am doing the following
void contacts::keyPressEvent(QKeyEvent *e)
{
if(ui.TextEdit->hasFocus())
{
//Alt + Enter deection
if ((e->key()==Qt::Key_Return) && (e->modifiers()==Qt::AltModifier))
{
//Alt + Enter pressed
}
//Enter pressed
else if (e->key()==Qt::Key_Return)
{
///Enter was pressed
}
}
}
However this does not detect the enter Key alone. Do you think I should use Event Filter for this ?? What if later on I decide to block a certain key and not have it processed ?

Related

Moving object using keyboard qt

I'm trying to move an object using my arrow keys, but when I launch the app, nothing happens. Do you have an idea on how to fix it ?
#Update : my rectangle only moves once to the left and to the right, but if I use qDebug it recognizes all the times I click left or right, any ideas ?
void MouvementJoueur::keyPressEvent(QKeyEvent *e)
{
switch ( e->key() )
{
case Qt::Key_Left:
rectangle->setPos(x()-10,y());
qDebug() << "You pressed the Key left";
break;
case Qt::Key_Right:
rectangle->setPos(x()+10,y());
qDebug() << "You pressed the Key right";
break;
}
}
Thank you in advance !
Your issue seems to be, that you take position of the parent, and set position of rectangle based on that. This is probably not what you want to do with key presses here. You should set the position like this:
rectangle->setPos(rectangle->x() - 10, rectangle->y());
You can refresh the GUI with the following command
view->processEvents();
and you can debug it. It detect the key press or not.
void MouvementJoueur::keyPressEvent(QKeyEvent *e)
{
if(e->key() == Qt::Key_Left)
{
rectangle->setPos(x()-10,y());
qDebug() << "You pressed the Key x";
}
if(e->key() == Qt::Key_Right)
{
rectangle->setPos(x()+10,y());
qDebug() << "You pressed the Key x";
}
}

QT: Ignore key events on checkbox selection

I have a QT Application on Windows which has a mode of using arrow keys, and also a mode which should totally ignore these arrow keys. That is, I want the arrow keys to not to trigger any event once the user checks a box.
I saw a post where eventFilter() was suggested, but I did not get how I could use it. Here is the checkbox event that listens the user, and gets triggered once the user checks it. In the else part I want the eventFilter() to work for arrow keys, but so far I could not get it running.
void MainWindow::on_checkBoxSmartCutMode_stateChanged(int arg1)
{
if (arg1 == 0)
{
// do as usual, arrow keys should work
}
else
{
eventFilter(); // if any arrow key is pressed, ignore the event
}
}
Any suggestions?
You can use keyEvent as your key filter by override keyPressEvent and test your checkbox state.
example:
void MainWindow::keyPressEvent(QKeyEvent *event)
{
// check your checkbox state
if (ui->poCheckBox->checkState() == Qt::Unchecked)
// do as usual, arrow keys should work
return;
switch(event->key())
{
case Qt::Key_Left:
case Qt::Key_Right: // add more cases as needed
event->ignore(); // if any arrow key is pressed, ignore the event
return;
}
// handle the event
}

How to check if a key sequence is press?

I would like to check if a key sequence is press. Like a password, i would like that to see the message box you must type "bcqwl" in right sequenze. I tried
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
while(true)
{
if(GetKeyState('B') & 0x8000)
{
cout<<"b has been press"<<endl;
if(GetKeyState('C') & 0x8000)
{
cout<<"c has been press"<<endl;
if(GetKeyState('Q') & 0x8000)
{
cout<<"Q has been press"<<endl;
if(GetKeyState('W') & 0x8000)
{
cout<<"W has been press"<<endl;
if(GetKeyState('L') & 0x8000)
{
MessageBox(NULL,"YES","YES",MB_OK);
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
else
{
continue;
}
}
}
But it doesn't works. He print "B has been press" ,many times but not infinitely times,if b is pressed. If after to press b I press c nothing happens.
So i tired:
step:
if(GetKeyState('B') & 0x8000)
{
cout<<"B has been press"<<endl;
goto step1;
}
else
{
goto step;
}
step1:
if(GetKeyState('C') & 0x8000)
{
MessageBox(NULL,"WORK","yes",MB_OK);
}
else
{
goto step;
}
But doesn't work.
I also tired:
#include <iostream>
#include <windows.h>
int main()
{
int progress = 0;
while(progress<=4)
{
if(GetKeyState('B') & 0x8000)
{
std::cout<<"b has been press"<<std::endl;
progress=1;
}
else
{
progress=0;
}
if(progress==1)
{
if(GetKeyState('C') & 0x8000)
{
std::cout<<"c has been press"<<std::endl;
progress=2;
}
else
{
progress=0;
}
}
if(progress==2)
{
if(GetKeyState('Q') & 0x8000)
{
std::cout<<"q has been press"<<std::endl;
progress=3;
}
else
{
progress=0;
}
}
if(progress==3)
{
if(GetKeyState('W') & 0x8000)
{
std::cout<<"w has been press"<<std::endl;
progress=4;
}
else
{
progress=0;
}
}
if(progress==4)
{
if(GetKeyState('L') & 0x8000)
{
std::cout<<"l has been press"<<std::endl;
progress=5;
}
else
{
progress=0;
}
}
}
return 0;
}
But that output "b has been press" for many times but not infinitely if i press b, and after if i press c nothing is happening, praticaly after press b and the program go in if(process==1) but if i press c nothing happen
P.S. sorry for my bad english.
The problem you are still having comes from the fact that you are in no way storing the progress in your key sequence.
Let's say your password is stored in a char array (for easier access to the single characters later on):
#define PWD_LEN 6 // bcqwl has a length of 5 characters but you need +1 for the '\0' (terminating character) at the end of your string
// ...
char password[PWD_LEN] = "bcqwl";
In addition you will need a counter:
#define PWD_LEN 5
// ...
char password[PWD_LEN] = "bcqwl";
int progress = 0;
while(true) { ... }
Both need to be stored before and outside the while loop because both store data that you don't want to reset in each iteration step in your loop.
The counter will be used to track the progress of the user towards completing the key sequence your password represents.
Whenever the user presses a key you will need to do the following checks:
Is the key allowed? - if you have a password abc but the user presses y or !, or something other then a, b or c the key is not allowed.
If the key is allowed take the character it represents and check if it's the same as the character in your password at index progress:
if ( key allowed )
{
if (password[progress] == '<your key character here>')
{
++progress;
}
else
{
// Handle incorrect key stroke relative to key sequence
}
}
Now in order to prevent the counter going bananas I would suggest doing all the checking upon key released, which unlike key pressed is a one time event. A key being pressed can also be part of key hold, in which case you will land in the else (from the code snippet above) many times, which might not be such a good idea.
If the key is ok and in terms of sequence it fits your password then you increase the progress so that in the next iteration step you can do the same check with a new released key event and a new index value for accessing your password array.
When your progress reaches the required value indicating that the key sequence is completed and that all the characters your password consists of have been "inserted" you can break the loop.
This is very basic so I hope that the instructions are clear enough for you to implement.
PREVIOUS ANSWER (now obsolete due to change in the question)
Unless other out-of-the-box way is available to do that (I haven't used GetKeyState() or anything else from windows.h) the general practice is to simply store the pressed state of each button (in an array, a struct etc.).
In your loop you can use a simple chain of if statements (but not nested like you do it!) to check which button is pressed during the current iteration step. Whenever a known key (one that you application wants to process) is pressed, you just need to toggle the respective state of that button in your array, struct or whatever other container you use to store this information:
while(true)
{
// Check state of supported buttons
if(GetKeyState('A') & 0x8000)
{
// store change of state of key A
}
if(GetKeyState('B') & 0x8000)
{
// store change of state of key B
}
if (...)
{
// ...
}
}
At the end or beginning of your while's body you can then ask for the state of each button and also make combined queries:
while(true)
{
// Check state of supported buttons
if(GetKeyState('A') & 0x8000)
{
// store change of state of key A
}
if(GetKeyState('B') & 0x8000)
{
// store change of state of key B
}
if (...)
{
// ...
}
// Do something
// Check for states of buttons
// ...
}
For example let's say you are using the following structure to store the key's state:
typedef struct Key
{
char keyCode;
bool pressed;
} Key;
Key keyA;
keyA.pressed = false;
you can simply do
if (keyA.pressed)
{
// Trigger some change that key 'A' controls
}
to check if your specific button is currently pressed and respectively trigger some action.
For key combinations things are not much different. You just need to use simply boolean logic to handle it:
if (keyA.pressed && keyB.pressed)
{
// Both key 'A' and 'B' are pressed - we have a key combo!
}
You can improve the readability of your code by storing all supported buttons in an array and even adding a nice enum to provide easy access to each button:
enum KeyCode
{
A,
B,
...
};
Key keys[n]; //with n being the number of keys you want to support and also the number of elements your enum has
// Access with an improved readability
if (keys[A].pressed && keys[B].pressed)
{
// ...
}
If you can't find any code for GetKeyState() in particular (highly unlikely) you can look at SDL for example.

ESC key for back to main interface

I have a problem with using the ESC key for back action. At the same time I want to receive user input too, but if the user wants to go back, they just press ESC key to go back. I tried to use while... getch(), but the problem is if I press backspace, the character that the user enters is not deleted.
Here is my code frame I made:
int main(){
do{
/* here I make my main interface */
if (choice == "1"){
/* here I wan to make [ESC] key for back to main interface
Press only one time then back and the same time can input
data */
}
...
else if (choice == "X" || choice == "x"){
flag = false
}
else{
wrongchoice();
}
}while(flag = true)
}

How to make keyword to work instantly with no delay in Qt::4.6 (C++)?

OS:: win xp sp3.
Qt:: 4.6
I have class Gameboard in which i have some rectangle.I defined keyPressEvent for that rectangle in order to move him around the screen.Key_A :: rectangle.moveToLeft & Key_D :: rectangle.moveToRight.Problem is that keys work with delay.
When i release one key and press another one it takes some time before that one begin to work.I checked Qt online documentation and now for that effect but dont now how to make those keys to work instantly without delay beetween them?
code snippet:
//in Gameboard class
ship = new QRect(x,y,w,h);
void Gameboard::keyPressEvent(QKeyEvent* event)
{
switch(event->key()) {
case Qt::Key_A :
{
x = x-10;
ship->moveTo(x,y);
break;
}
case Qt::Key_D :
{
x = x+10;
ship->moveTo(x,y);
break;
}
}
}
Put input cursor into any applicable text box and press the 'A' key. What you'll see is once you press the key, letter 'A' will be printed, then there will be a pause, and then first letter 'A' will be quickly followed by many others. That's the way keypress events work. And your program is receiving them exactly like this. First you receive one event when the key is actually pressed, and then after a delay you get a lot of automatically repeated events, in case user wants to enter one character many-many times.
It works perfectly for text input, but in games you usually need smooth movement. If that's the case, you need to move your ship not upon receiving the event, but regularly, for example, on timer event. And you will need to catch both keyPressEvent and keyRelease event and use them to remember what movement keys are currently pressed. So you could for example do this:
struct Ship {
bool is_moving_left, is_moving_right;
QPoint position;
int speed;
...
void timerEvent()
{
if (is_moving_left) position.setX (position.x() - speed);
if (is_moving_right) position.setX (position.x() + speed);
}
...
};
...
void Gameboard::keyPressEvent (OKeyEvent *_event)
{
switch(event->key()) {
case Qt::Key_A :
ship->is_moving_left = true;
break;
case Qt::Key_D :
ship->is_moving_right = true;
break;
}
}
...
void Gameboard::keyReleaseEvent (OKeyEvent *_event)
{
switch(event->key()) {
case Qt::Key_A :
ship->is_moving_left = false;
break;
case Qt::Key_D :
ship->is_moving_right = false;
break;
}
}
Then just make sure Ship::timerEvent() gets called on every timer event in the game.