Qt input dialog - enter value without closing - c++

I have QtInputDialog and I dont like it that, when i press enter it closes.
I would like to type value and confirm it by pressing enter on keyboard. After that line edit resets and i can type another value.

Dialog initialization:
void MainWindow::on_button1_clicked() {
dialog = new QInputDialog();
dialog->installEventFilter(this);
dialog->show();
}
Event filter:
bool MainWindow::eventFilter(QObject *o, QEvent *e) {
if (e->type() == QEvent::KeyPress) {
if (static_cast<QKeyEvent*>(e)->matches(QKeySequence::InsertParagraphSeparator)) {
qDebug() << dialog->textValue(); //use this value as you wish
dialog->setTextValue(QString());
return true; //block this event
}
}
return false;
}
Note that the dialog still can be closed using mouse click on "OK".

Related

Qt: eventFilter does not recieve KeyPress when QCompleter is shown

I have an subclassed QPlainTextEdit called Editor. The editor contains an object used to suggest text, called a Suggester. The user can press a button from the Suggester to show a QCompleter, the activeCompleter.
I need to mess with the activeCompleter when KeyPress events come in from the Editor, so in Suggester, I create an eventFilter and install it to the passed in Editor instance.
When the activeCompleter is not shown, the eventFilter receives the KeyPress events as expected. However, when the activeComplter is shown via activeComplter->complete(), the eventFilter does not recieve KeyPress events (the editor behaves however).
I don't understand why this is. The QCompleter is not a widget. The Editor retains focus. I do not intercept events or keys anywhere else.
Why is my eventFilter not receiving KeyPress events?
relevant code...
Editor::Editor(QWidget *parent) : QPlainTextEdit(parent){
suggester = new Suggester(this);
}
Suggester::Suggester(Editor* editor){
this->editor = editor;
editor->installEventFilter(this);
}
bool Suggester::eventFilter(QObject *obj, QEvent *event){
qDebug()<< "event filter of type " << event->type() << " from " << obj;
return false;
}
It seems that your eventFilter member is incomplete. You have to filter the QEvent:KeyPress event as follows:
bool Suggester::eventFilter(QObject *obj, QEvent *event)
{
if (obj == textEdit) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
qDebug() << "Ate key press" << keyEvent->key();
return true;
} else {
return false;
}
} else {
// pass the event on to the parent class
return Suggester::eventFilter(obj, event);
}
}

How to avoid edit mode when I advance with TAB key after edit a cell in a QTableView?

This is my question. When I edit a cell in a QTableView, I would like that if I press TAB key, the current cell is updated, but the next cell isn't in edit mode.
I have try to create a eventFilter in a table, but it doesn't work. Neither if I create the eventFilter in the editor widget of the delegate.
This is my try of a eventFilter in the QTableView. My idea is that if the current cell is in the last column and row and the current row is not empty, I insert another row (this works fine) and if I am editing any cell, when I press TAB I can place on the next cell but without Edit Mode
This is a snippet of the code:
bool MiTabla::eventFilter(QObject *watched, QEvent *e)
{
if (e->type() == QEvent::KeyPress)
{
QModelIndex indice = this->currentIndex();
QKeyEvent *ke =static_cast<QKeyEvent*>(e);
switch (ke->key())
{
case (Qt::Key_Delete):
{
if (this->selectionModel()->isRowSelected(indice.row(),QModelIndex()))
{
//borrarLineas();
}
else
{
this->model()->setData(this->currentIndex(),"",Qt::EditRole);
}
break;
}
case (Qt::Key_Tab):
{
if (indice.row() == this->model()->rowCount(QModelIndex())-1
&& indice.column() == this->model()->columnCount(QModelIndex())-1
&& !NombreVacio())
{
this->model()->insertRow(this->model()->rowCount(QModelIndex()));
QModelIndex ind = this->model()->index(indice.row()+1,0);
this->setCurrentIndex(ind);
}
else //this doesn't work
{
QModelIndex ind = this->model()->index(indice.row(),indice.column()+1);
this->setCurrentIndex(ind);
}
break;
Thank you. I have solved it as you said.
I have reimplement the eventFilter() function in the delegate class (subclassed from QStyledItemDelegate) as below:
bool DelegadoNombre::eventFilter(QObject *obj, QEvent* event)
{
if (event->type()==QEvent::KeyPress)
{
QKeyEvent* key = static_cast<QKeyEvent*>(event);
if (key->key()==Qt::Key_Tab || key->key()==Qt::Key_Enter || key->key()==Qt::Key_Return)
{
QLineEdit *editor=qobject_cast<QLineEdit*>(obj);
emit commitData(editor);
emit closeEditor(editor, QStyledItemDelegate::NoHint);
}
else
{
return QObject::eventFilter(obj, event);
}
return false;
}
else
{
return QObject::eventFilter(obj, event);
}
return false;
}
This function says to editor of the delegate that if Tab Key is pressed it must commit the data and close the editor but no open the next editor in Edit Mode QStyledItemDelegate::NoHint.
Also, return false for allow to the table use this event

How to focus menuBar() with Qt

I have a working application. I added a menuBar() to the main window with some menus. Then, I hid it to free screen space. I wrote the code below so that when user presses ALT key, the menu bar appears if it's hidden, and it hides if it's displayed.
void MainWindow::keyPressEvent( QKeyEvent *k ) {
if(k->modifiers() & Qt::AltModifier) {
menuBar()->setHidden(!menuBar()->isHidden());
if(menuBar()->hasFocus()) {
QMessageBox::information(this, "Info", "Focus !");
}
}
}
As you can see, I also added a QMessageBox to see when the menuBar has the focus. And this box appears only half of the time. It goes like this :
Application launched, menubar hidden
I press ALT, menubar displayed, no message box, no focus
I press ALT, menubar hidden
I press ALT, menubar displayed, message box, focus
I press ALT, menubar hidden
I press ALT, menubar displayed, no message box, no focus
I press ALT, menubar hidden
I press ALT, menubar displayed, message box, focus
etc.
How to make sure when the menuBar is displayed, it always has focus ?
I wanted to do the same thing. My solution, complete example, as a gist:
https://gist.github.com/xim/ee56564f425151ea2fa70f730d644873
Tested against Qt 5.9.4.
As it contains a lot of other junk, a minimal example:
class AutoHidingMenuBar : public QMenuBar {
Q_OBJECT
public:
AutoHidingMenuBar() : QMenuBar() {
setMaximumHeight(0);
connect(qApp, &QApplication::focusChanged, this, &AutoHidingMenuBar::focusChanged);
}
private slots:
void focusChanged(QWidget *from, QWidget *to) {
bool inFocus = hasFocus() || isAncestorOf(focus) || hasFocusedChild();
if (inFocus && maximumHeight() == 0) {
auto action = activeAction();
setMaximumHeight(100);
if (action) {
// XXX This is a bit of a hack. We could do
// QCoreApplication::processEvents();
// setActiveAction(action);
// with almost the same effect, but then we *open* the first menu on single alt press...
auto evt = new QMouseEvent(QEvent::MouseMove, actionGeometry(action).center(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
QCoreApplication::postEvent(this, evt);
}
} else if (!inFocus && maximumHeight() != 0)) {
setMaximumHeight(0);
}
}
private:
bool hasFocusedChild() {
QObjectList queue{children()};
while (!queue.empty()) {
auto child = queue.takeFirst();
auto widget = dynamic_cast<QWidget *>(child);
if (widget && widget->hasFocus())
return true;
queue.append(child->children());
}
return false;
}
};
Have you tried just adding the setFocus command?
void MainWindow::keyPressEvent( QKeyEvent *k ) {
if(k->modifiers() & Qt::AltModifier) {
menuBar()->setHidden(!menuBar()->isHidden());
menuBar()->setFocus(Qt::MenuBarFocusReason);
if(menuBar()->hasFocus()) {
QMessageBox::information(this, "Info", "Focus !");
}
}
}

Qt Tab rename when double clicked

i am using visual Studio with Qt.
i do not have access to Qt designer. its all done through coding (C++);
i have an opensource software called easypaint.
i got stuck at trying to rename tabs. I want to be able to rename tabs when user double clicks on the tab itself.
i created a new function to filter the doubleClick event :
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
`enter code here`{
if (event->type() == QEvent::MouseButtonDblClick) {
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}
then i added this line to a function that initializes the TabWidget:
installEventFilter(mTabWidget);
can anyone please guide me through this.
Thank you
Most likely Qt doesn't allow an inline editor to open on the tab's name. So you'd most likely have to create and run a very small QDialog to query for the new name:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == mTabWidget &&
event->type() == QEvent::MouseButtonDblClick) {
// query and set tab(s) names
QTabWidget *tab = qobject_cast<QTabWidget *>(obj);
if(tab)
{
QDialog dlg;
QVBoxLayout la(&dlg);
QLineEdit ed;
la.addWidget(&ed);
QDialogButtonBox bb(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
la.addWidget(&bb);
dlg.setLayout(&la);
if(dlg.exec() == QDialog::Accepted)
{
tab->setTabText(0, ed.text());
return true;
}
}
}
// Standard event processing
return QObject::eventFilter(obj, event);
}
It might be that Qt's dynamic memory management doesn't like the local class instances, so you'd have to convert all those class instances created to pointers created with new, but then please don't forget to tell the QDialog to delete on close or call dlg->deleteLater() after you queried the new name.
Another way to solve this via a fake inline editor would need a bit more work:
create a QLineEdit
move it right above the tab's, bring it up front and set keyboard focus to it
wire signals and slots
pressing enter should use the contents of the QLineEdit
leaving focus from the line edit should be treated as "abort" and delete the line editor
implement the slots to do what's needed.
You can write the event filter in the fallowing way:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == mTabWidget &&
event->type() == QEvent::MouseButtonDblClick) {
QTabWidget *tab = qobject_cast<QTabWidget *>(obj);
// Set tab(s) names
tab->setTabText(0, "New Name");
}
// Standard event processing
return QObject::eventFilter(obj, event);
}

Qt5 C++: Subclassing QSpinBox and keyPressEvent won't work

I want to track when the enter/return key is pressed and then to focus on some other widget but if it's not pressed than spinbox should take normal action instead of anything else. I've subclassed QSpinBox and created protected void keyPressEvent(QKeyEvent *event). Inside it is this code:
void MytSpinBox::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Return) {
qDebug() << "return pressed";
editingFinished();
} else {
qDebug() << "Other key";
event->accept();
}
}
This code should work, but it doesn't. I don't know what's wrong, but when I focus on promoted spinbox and try to change number in it, it just won't work, I only get the debug message printed. If I push enter/return key than it print debug message and focus on some other widget which I set in editingFinished().
What am I doing wrong?
If you need to invoke default processing of the event, you need to call base class implementation:
void MytSpinBox::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Return) {
qDebug() << "return pressed";
editingFinished();
} else {
QSpinBox::keyPressEvent(event);
}
}