How to type TAB in QLineEdit? - qt

When I type tab in QLineEdit, I go to the next widget. How to disable this behavior and type the TAB character in the QLineEdit box?

You need to check the keys via handle:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == m_lineEdit)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Tab)
{
//do here
return true;
}
}
//return event to the parent class
return QMainWindow::eventFilter(obj, event);
}
Or you can create your own class inherited from QLineEdit and overload the method:
void LineEdit::keyPressEvent(QKeyEvent* event)
{
if (keyEvent->key() == Qt::Key_Tab)
{
emit tabPressed();
return;
}
QLineEdit::keyPressEvent(event);
}

Related

QMainWindow not receiving keyPressEvent, even with event filter

I'm trying to design an image viewer application where I use a QGraphicsView to display my images. I want to enable the user to use the arrow keys to open the next/previous image, but my QGraphicsView is always consuming my keyPressEvent. I would like these events to be handled by my QMainWindow class instead. I realize this is a common issue, and apparently I can solve it by installing an event filter and/or ensuring that my QMainWindow can have focus. I have done both, but so far the only thing I have done is to not let the QGraphicsView get the event, but it still does not propagate to the QMainWindow. So far I've implemented the eventFilter method in my QMainWindow class and installed it on my QGraphicsView object.
QMainWindow class
IVMainWindow::IVMainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle("ImageViewer++");
setFocusPolicy(Qt::StrongFocus); // Enabled the QMainWindow to get focus
m_image_widget = new IVImageWidget();
m_image_widget->installEventFilter(this); // Install event filter on QGraphicsView
setCentralWidget(m_image_widget);
resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);
// For DEBUG purpose
loadImage("res/image.png");
createMenuBar();
createToolBar();
}
/**
* Filters out arrow key presses.
*/
bool IVMainWindow::eventFilter(QObject *obj, QEvent *event) {
if (event->type() == QEvent::KeyPress) {
auto *keyEvent = static_cast<QKeyEvent *>(event);
int key = keyEvent->key();
// Return true to reject the key-presses
return (key == Qt::Key_Left || key == Qt::Key_Right || key == Qt::Key_Up || key == Qt::Key_Down);
} else {
// standard event processing
return QMainWindow::eventFilter(obj, event);
}
}
//Never gets to this point, unless I explicitly give it focus by clicking on some other widget than the QGraphicsView...
void IVMainWindow::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::RightArrow) {
m_logger.Debug("Right arrow pressed.");
} else if (event->key() == Qt::LeftArrow) {
m_logger.Debug("Left arrow pressed.");
}
}
You need to process the event in the event filter, it is ok to call QMainWindow::eventFilter for sanity but it do not
process the event as an incoming event, so the event handlers will not be called.
bool IVMainWindow::eventFilter(QObject *obj, QEvent *event) {
if (event->type() == QEvent::KeyPress) {
auto *keyEvent = static_cast<QKeyEvent *>(event);
int key = keyEvent->key();
// Return true to reject the key-presses
if (key == Qt::Key_Left || key == Qt::Key_Right || key == Qt::Key_Up || key == Qt::Key_Down)
{
//process event here somehow, or instruct your class to do it later
return true; //filter the event
}
} else {
// standard event processing
return QMainWindow::eventFilter(obj, event);
}
}
//This will only be called for the 'real' events, the ones that eventually are received by the main window
void IVMainWindow::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::RightArrow) {
m_logger.Debug("Right arrow pressed.");
} else if (event->key() == Qt::LeftArrow) {
m_logger.Debug("Left arrow pressed.");
}
}

How to get a line after Key_Return press in QTextEdit

I get characters in my QTextEdit. After pressing an Enter key I want to get the line before the key and parse it.
static QString term_str;
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->textEditTerminalTx)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Return)
{
//term_str += '\r';
QByteArray ba = term_str.toLocal8Bit();
char *str = ba.data();
compars.ParseCommand(str);
term_str.clear();
}
else
{
if (keyEvent->key() != Qt::Key_Backspace && keyEvent->key() != Qt::Key_Delete)
term_str += static_cast<char> (keyEvent->key());
return false;
}
}
else
return false;
}
else
return MainWindow::eventFilter(obj, event);
}
And I get but in upper case.
If I type - test - in textEditTerminalTx and in term_str I see TEST
Why the function is ignoring the CapsLock key?
If you want to get the character pressed then you must use the text() method instead of using key() since the latter does not have the information to differentiate between upper and lower case.
// ...
if (keyEvent->key() != Qt::Key_Backspace && keyEvent->key() != Qt::Key_Delete)
term_str += keyEvent->text();
// ...

How to get a current index before return in eventFilter handler?

When I move a current index with Key_Up or Key_Down in treeView, I found out that the moved current index is only applied after this line return QWidget::eventFilter(watched, event);. How can I get a newly moved index before return QWidget::eventFilter(watched, event); ? I tried to change the moved current index by manual with currentIndex = currentIndex-1; but it didn't work.
bool TipManager::eventFilter(QObject *watched, QEvent *event)
{
if(watched == ui->treeView && event->type() == QEvent::KeyPress){
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
QModelIndex currentIndex = ui->treeView->currentIndex();
if( keyEvent->key() == Qt::Key_Up )
{
//currentIndex = currentIndex-1;
}
if( keyEvent->key() == Qt::Key_Down )
{
//currentIndex = currentIndex+1;
}
if(currentIndex.isValid())
{
ui->treeView->setCurrentIndex(currentIndex);
trimCurrentPath(currentIndex);
}
}
return QWidget::eventFilter(watched, event);
}
You can simply first pass the event down, then check the index:
bool TipManager::eventFilter(QObject *watched, QEvent *event)
{
bool const ret = QWidget::eventFilter(watched, event);
if(watched == ui->treeView && event->type() == QEvent::KeyPress){
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
QModelIndex currentIndex = ui->treeView->currentIndex();
if( keyEvent->key() == Qt::Key_Up )
{
//currentIndex = currentIndex-1;
}
if( keyEvent->key() == Qt::Key_Down )
{
//currentIndex = currentIndex+1;
}
if(currentIndex.isValid())
{
ui->treeView->setCurrentIndex(currentIndex);
trimCurrentPath(currentIndex);
}
}
return ret;
}
But I guess that actually the index is changed only after leaving your eventFilter(watched, event)...

QT QLineEdit focusout

I have a QLineedit with mask and qvalidator (subclassed)
How can i prevent to move away the focus if the input isn't match the mask or validator ?
Because neither mask nor qvalidator don't prevent to move away focus from QLineEdit.
And editingfinished isn't work because :
void QLineEdit::editingFinished()
This signal is emitted when the Return or Enter key is pressed or the line edit loses focus. Note that if there is a validator() or inputMask() set on the line edit and enter/return is pressed, the editingFinished() signal will only be emitted if the input follows the inputMask() and the validator() returns QValidator::Acceptable."
void MainWindow:n_lineEdit_editingFinished()
{
if (ui->lineEdit->text() != "1111") ui->lineEdit->setFocus();
}
So mask (an validator) doesn't work together with editingFinsihed signal.
plus i have tried this
bool MainWindow::eventFilter(QObject *filterObj, QEvent *event)
{
if (filterObj == ui->lineEdit ) {
if(event->type() == QEvent::FocusOut) {
if (ui->lineEdit->text() != "1111") { ui->lineEdit-`>setFocus();};
return true;
};
};
return false;
}
thank you Attila
From the Qt's doc:
Note that if there is a validator set on the line edit, the
returnPressed()/editingFinished() signals will only be emitted if the
validator returns QValidator::Acceptable.
But you can set a focus on every event, not only for FocusOut:
bool MainWindow::eventFilter(QObject *filterObj, QEvent *event)
{
if (filterObj == ui->lineEdit )
ui->lineEdit->setFocus();
if(event->type() == QEvent::KeyRelease)
{
QKeyEvent* e = (QKeyEvent*)event;
if(e->key() == Qt::Key_Return
|| e->key() == Qt::Key_Enter)
{
/* do what you want here */
}
}
return QObject::eventFilter(filterObj, event); // usual process other events
}

QlineEdit selectAll doesn't work?

I use folowing code. In it lineEdit->selectAll() works called by pushButton and only at first launch called by eventFilter. Although label->setText works all time propperly. Why?
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
ui->lineEdit->installEventFilter(this);
}
void Widget::on_pushButton_clicked()
{
ui->lineEdit->selectAll();
}
bool Widget::eventFilter(QObject *object, QEvent *event)
{
if (object == ui->lineEdit && event->type() == QEvent::FocusIn )
{
ui->lineEdit->selectAll();
ui->label->setText("Focused!");
return false;
}
if (object == ui->lineEdit && event->type() == QEvent::FocusOut )
{
ui->label->setText("unFucused!");
return false;
}
return false;
}
UPD: Did what Ilya recomended. Still have same problem.
void myLine::focusInEvent(QFocusEvent* event)
{
setText("Focused!");
selectAll();
}
void myLine::focusOutEvent(QFocusEvent* event)
{
setText("UnFocused!");
}
Found answer here Select text of QLineEdit on focus
Instead ui->lineEdit->selectAll()
should use QTimer::singleShot(0,ui->lineEdit,SLOT(selectAll())),
because mousePressEvent trigers right after focusInEvent so text selected in focusInEvent unselects by mousePressEvent.
Not really answering the question, but there's a more "standard" way of customizing these events.
Create a QLineEdit subclass and define your own focusInEvent / focusOutEvent handlers.
If you're using the UI Designer, promote your lineEdit to your subclass (right-click > "Promote to").
Because you use eventFilter in a wrong way:
bool Widget::eventFilter(QObject *object, QEvent *event)
{
if (object == ui->lineEdit && event->type() == QEvent::FocusIn )
{
ui->lineEdit->selectAll();
ui->label->setText("Focused!");
}
if (object == ui->lineEdit && event->type() == QEvent::FocusOut )
{
ui->label->setText("unFucused!");
}
return QWidget::eventFilter(object, event);
}

Resources