QKeyEvent keyPressEvent not detecting arrow keys? - c++

I have a program that captures a single key press and then outputs the key that is being pressed. The problem is, I am not able to return the value of the key being pressed and cannot get the arrow keys to output anything at all. Here's my code:
myApp.h
class someClass: public QDialog
{
Q_OBJECT
public:
...<snip>...
private:
...<snip>...
protected:
void keyPressEvent(QKeyEvent *e);
};
myApp.cpp
MyApp::MyApp(QWidget *parent) :
QDialog(parent),
ui(new Ui::myApp)
{
QWidget::grabKeyboard();
ui->setupUi(this);
}
void someClass::keyPressEvent(QKeyEvent *e)
{
qDebug() << "You typed " + e->key();
}
There are two issues here. First, when I type any key, I get output like the following in the Debug pane:
gw492_32\include/QtCore/qstring.h
w492_32\include/QtCore/qstring.h
492_32\include/QtCore/qstring.h
92_32\include/QtCore/qstring.h
I typed abcd to get the above. Shouldn't key() give me the integer value of the key pressed?
The second issue is that when I hit one of the arrow keys, I get nothing in the debug pane except for a blank line. Again, shouldn't I be seeing the integer value for the Up arrow? (values for keys listed here). How would I then output the ASCII value for the key?
Any help is appreciated.

The output definitely looks like unwanted pointer arithmetic is happening. And it's undefined behavior.
"You typed " + e->key()
advances the pointer to "You typed " by e->key() and makes it point to another location, which is in this case occupied by the string you're getting as output.
If you want to print it properly, do any of the following:
qDebug() << "You typed " << e->key();
qDebug() << "You typed " + QString::number(e->key());
qDebug() << QString("You typed %1").arg(e->key());

Related

How can I make Qt recognize a sequence of keys?

In my current application, I need to make QT close a window by pressing Shift + Eesc or by pressing Esc 3x.
First, I tried Shift + Esc, it went this way
if ((event->key() == Qt::Key_Escape) && (event->key() == Qt::Key_Shift))
{
cout << "test" << endl;
on_close_x_button_clicked();
}
But for some reason, it just doesn't work. I googled it and found something about a QKeySequence but I didn't find any example of how to do it properly. I tried some ways with no success like:
if ((event->key() == Qt::QKeySequence(Qt::Key_Escape + Qt::Key_Shift)))
{
cout << "teste" << endl;
on_close_x_button_clicked();
}
}
But again, no dice. Can someone point me how to proper implement this functionality?
I also could not find anything that allowed me to create an event based on pressing Escape key 3x. Can someone, please, also teach me how to do it?
I also tried using Shortcuts, and it went like this:
LinAdvancedTestWidget::LinAdvancedTestWidget(QWidget *parent,
QObject *event_filter,
SystemEvent *event, int dpi)
: AdvancedTestWidget(parent, event_filter, event) {
(void)dpi;
KeyShiftEsc = new QShortcut(this);
KeyShiftEsc->setKey(Qt::Key_Shift + Qt::Key_Escape);
connect(KeyShiftEsc, SIGNAL(activated()), this, SLOT(slotShortcutShiftEsc()));
}
void LinAdvancedTestWidget::slotShortcutShiftEsc()
{
cout << "Escape LinAdvancedTestWidget" << endl;
on_close_x_button_clicked();
}
But it again, also does not work :/
Shift is a modifier, not a key, as you seem to compare. You would need to write something like this:
if ((event->key() == Qt::Key_Escape) && (event->modifiers() & Qt::Key_Shift))
{
...
}
Also, it is better if you use the QWidget::addAction(...) method as:
QAction *action = new QAction("my action", "Shift+Esc");
myWidget->addAction(action);
You can also set multiple shortcuts on an action:
action->setShorcuts({"Shift+Esc", QKeySequence(Qt::Key_Esc, Qt::Key_Esc, Qt::Key_Esc)});

Issues trying to make a filter using Qt

I'm trying to make my software filter a list of elements.
I think I need to put my data in a TableWidget because I have to display other information.
I also put 3 Line Edit to search respectively in each category (called leName, leSource, leDestination)
so I tried to implement my filter for the name property, for now I have :
void MyClass::on_leName_textEdited(const QString &arg1)
{
for (int i=0;ui->tableWidget->rowCount()-1;i++)
{
qDebug()<<"before if";
if(ui->tableWidget->item(0,1)->text().contains(arg1) //tried with &arg1, I have the same issue, for now
{
qDebug()<<"If validated";
ui->tableWidget->showRow(i);
}else{
qDebug()<<"If not validated"
ui->tableWidget->hideRow(i)
}
}
}
When I hit a key, my soft crashes
I get "Before if", "If (not) validated", "Before if" from qDebug
I launched with debbugger and got Segmentation fault as error
not sure what I could add as detail about my error
Maybe I did nothing in the good way, I'm no expert in Qt nor c++
If you have any idea of what I should do to correct this, I would appreciate it =)
The fact that a cell exists does not imply that it has an associated QTableWidgetItem, so you must verify that it is not null.
QTableWidgetItem * item = ui->tableWidget->item(0, 1);
if(item && item->text().contains(arg1))
{
qDebug() << "If validated";
ui->tableWidget->showRow(i);
}else{
qDebug() << "If not validated"
ui->tableWidget->hideRow(i)
}

Get original key as though without shift modifier

I want to create keyboard bindings, which work at least similarly on different keyboard layouts. My problem is that the shift modifier converts keys into different keys, as detailed in the documentation: http://doc.qt.io/qt-5/qkeysequence.html#keyboard-layout-issues
Is there any way to find out the original key irrespective of the keyboard layout?
E.g. find out that . is pressed when shift+. is pressed.
See also this (currently unanswered) quesion: get shift+numerical keys in qt using qkeyevent
In Windows you can use MapVirtualKeyA and MAPVK_VK_TO_CHAR to get the unshifted key. MapVirtualKeyA needs the virtual key, which can be get using QKeyEvent::nativeVirtualKey.
Note: When pressing modifiers only QKeyEvent::key() may report a false character, the virtual key helps to distinguish these cases.
Example
void MainWindow::keyPressEvent(QKeyEvent* ke)
{
const auto vk = ke->nativeVirtualKey();
const auto unshifted_key = MapVirtualKeyA(vk, MAPVK_VK_TO_CHAR);
qDebug() << "Original key:" << (char)ke->key();
qDebug() << "Unshifted key:" << (char)unshifted_key;
if (unshifted_key > 0) {
// Printing the full key sequence just for comparison purposes
QString modifier;
if (ke->modifiers() & Qt::ShiftModifier) modifier += "Shift+";
if (ke->modifiers() & Qt::ControlModifier) modifier += "Ctrl+";
if (ke->modifiers() & Qt::AltModifier) modifier += "Alt+";
if (ke->modifiers() & Qt::MetaModifier) modifier += "Meta+";
const QKeySequence ks(modifier + QChar(ke->key()));
qDebug() << "Full key sequence:" << ks.toString();
}
}
The full source code for the example can be found in here.

is it possible to "update" a QTextCursor?

In a QTextEdit object, let's say I want to know the character's position under the mouse cursor.
I can write...
void MyQTextEditObject::mousePressEvent(QMouseEvent* mouse_event) {
mycursor = this->textCursor();
qDebug() << "pos=" << mycursor.position();
}
... it works (the mouse position changes from 0 to the last index of the last character) but the mousePressEvent() method creates a new cursor every time an event occurs. It bothers me since I don't know the "cost" of such a creation.
So, why not create a cursor attribute and use it in mousePressEvent() ?
Something like :
class MyQTextEditObject : public QTextEdit {
Q_OBJECT
public:
// [...]
QTextCursor cursor;
}
MyQTextEditObject::MyQTextEditObject(QWidget* parent) : QTextEdit(parent) {
// [...]
this->cursor = this->textCursor();
}
void MyQTextEditObject::mousePressEvent(QMouseEvent* mouse_event) {
qDebug() << "pos=" << this->cursor.position();
}
But the position doesn't change anymore, as if it was fixed. So, is there a way to somehow update the cursor ? Or is the cost of repeated creation of a QTextCursor insignificant ?
update : writing something like...
mycursor= this->cursorForPosition(mouse_event->pos());
... creates a new cursor and seems to be the equivalent to :
mycursor= this->textCursor();
In your first example, instead of
mycursor = this->textCursor();
qDebug() << "pos=" << mycursor.position();
why do not you call it directly as?
qDebug() << "pos=" << this->textCursor().position();
Because in python
self.textCursor().position()
works.
Also, I am not sure but in your second example maybe you need to set the "cursor" as "textCursor" again with setTextCursor().
void MyQTextEditObject::mousePressEvent(QMouseEvent* mouse_event) {
this->setTextCursor(cursor)
qDebug() << "pos=" << this->cursor.position();
}

Capturing modifier keys Qt

I am trying to understand how to handle various events with Qt and have found an issue I cannot understand with key modifiers e.g. Ctrl Shift Alt etc. I have made a default Qt GUI Application in Qt Creator extending QMainWindow and have found that the following example does not produce understandable results.
void MainWindow::keyPressEvent(QKeyEvent *event)
{
qDebug() << "Modifier " << event->modifiers().testFlag(Qt::ControlModifier);
qDebug() << "Key " << event->key();
qDebug() << "Brute force " << (event->key() == Qt::Key_Control);
}
Using the modifiers() function on the event never is true while the brute force method returns the correct value.
What have I done wrong?
Try using this to check for shift:
if(event->modifiers() & Qt::ShiftModifier){...}
this to check for control:
if(event->modifiers() & Qt::ControlModifier){...}
and so on. That works well for me.
EDIT:
To get the modifiers of a wheel event, you need to check the QWheelEvent object passed to your wheelEvent() method:
void MainWindow::wheelEvent( QWheelEvent *wheelEvent )
{
if( wheelEvent->modifiers() & Qt::ShiftModifier )
{
// do something awesome
}
else if( wheelEvent->modifiers() & Qt::ControlModifier )
{
// do something even awesomer!
}
}
According to the documentation, QKeyEvent::modifiers cannot always be trusted. Try to use QApplication::keyboardModifiers() static function instead.
From Qt 5 Doc. – Qt::KeyboardModifiers QKeyEvent::modifiers() const:
Warning: This function cannot always be trusted. The user can confuse it by pressing both Shift keys simultaneously and releasing one of them, for example.