C++ Qt QCloseEvent doesn't work - c++

I want to create a message which appears in a new window when the user presses the exit button. Therefor I create a QCloseEvent, but the MainWindow actually doesn't close at all. What am I doing wrong?
Mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
//Constructor
explicit MainWindow(QWidget *parent = 0);
//Destructor
~MainWindow();
public slots:
void closeMainWindow();
private:
QCloseEvent *event;
MainWindow.cpp
void MainWindow::closeMainWindow(){
event = new QCloseEvent();
QMessageBox::StandardButton answer = QMessageBox::question(
this,
tr("Close the Window"),
tr("Do you want to close the window?"),
QMessageBox::Yes | QMessageBox::No);
if(answer == QMessageBox::Yes){
event->accept();
}
else
event->ignore();
}

You must implement closeEvent function of mainwindow!
e.g
void MyMainWindow::closeEvent(QCloseEvent *event)
{
QMessageBox::StandardButton answer = QMessageBox::question(
this,
tr("Close the Window"),
tr("Do you want to close the window?"),
QMessageBox::Yes | QMessageBox::No);
if(answer == QMessageBox::Yes){
event->accept();
}
else
event->ignore();
}

You are missing close() function
if(answer == QMessageBox::Yes)
{
event->accept();
close();
}
or override closeEvent() function of MainWindow
Refer below link:
Generating a QCloseEvent won't close QMainWindow

Related

Implemented a QKeyEvent but how does the keyPressEvent() gets called

keypress.h
#ifndef KEYPRESS_H
#define KEYPRESS_H
#include <QObject>
#include <QKeyEvent>
class keypress : public QObject {
Q_OBJECT public:
explicit keypress(QObject *parent = nullptr);
void keyPressEvent(QKeyEvent *e);
};
#endif // KEYPRESS_H
keypress.cpp
#include "keypress.h"
#include <QDebug>
keypress::keypress(QObject *parent)
: QObject{parent}
{
}
void keypress::keyPressEvent(QKeyEvent *e)
{
qDebug() <<"Key clicked : "<<e->key();
}
I am new to QKeyEvent and I am not able to call the keyPressEvent function. Should i call the keyPressEvent function inside the constructor?
I also have to display a connect with keyPressEvent function and a timer of 50 milli seconds even if it doesn't receive any keypress.
Thanks in Advance!
If you want to implement keyPressEvent in the widget/dialog/control, you can override keyPressEvent.
Here is another link:
QWidget keyPressEvent override
if you want to implement key press yourself and installed on other widgets, you can refer to the code below,
From QObject::installEventFilter,
class KeyPressEater : public QObject
{
Q_OBJECT
...
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};
bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
qDebug("Ate key press %d", keyEvent->key());
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}
And here's how to install it on two widgets:
KeyPressEater *keyPressEater = new KeyPressEater(this);
QPushButton *pushButton = new QPushButton(this);
QListView *listView = new QListView(this);
pushButton->installEventFilter(keyPressEater);
listView->installEventFilter(keyPressEater);
Hope it helps you.

Program crashes on close Event in Qt

I was trying to set the close event to my code but when I set this code my program crashes.
mainwindow.cpp
void MainWindow::closeEvent(QCloseEvent *event)
{
event->ignore();
if (QMessageBox::Yes == QMessageBox::question(this, "Close Confirmation?",
"Are you sure you want to exit?",
QMessageBox::Yes|QMessageBox::No))
{
if(QMessageBox::Yes)
{
if(aboutDialog)
{
aboutDialog->close();
event->accept();
}
event->accept();
}
}
}
void MainWindow::showAboutDialog()
{
aboutDialog = new QDialog;
Ui::About aboutUi;
aboutUi.setupUi(aboutDialog);
connect(aboutUi.Close, SIGNAL(pressed()), aboutDialog, SLOT(close()));
aboutDialog->show();
}
mainwindow.h
private:
QDialog *aboutDialog;
I am confused why this happens. Help me out to solve this!
Don't ignore the event if you're planning to close, try this:
void MainWindow::closeEvent(QCloseEvent *event)
{
if (QMessageBox::Yes != QMessageBox::question(this, "Close Confirmation?",
"Are you sure you want to exit?", QMessageBox::Yes | QMessageBox::No))
{
event->ignore();
}
}
And when creating the aboutDialog-box, you should pass the mainWindow as parent as Nejat's comment suggests: aboutDialog = new QDialog(mainWindow);. This will make sure that the aboutDialog will get closed if the main window closes.

Qt C++ how to use keyPressEvent for a QWidget within a class

I'm trying to use a keyPressEvent, but it is only working when the window has focus and not any of the QWidgets.
Here is my code:
In customdialog.h:
class CustomDialog : public QDialog, public Ui::CustomDialog
{
Q_OBJECT
private:
Ui::CustomDialog *ui;
QString lastKey;
public:
CustomDialog(QWidget * parent = 0);
protected:
void keyPressEvent(QKeyEvent *e);
};
In customdialog.cpp:
void CustomDialog::keyPressEvent(QKeyEvent *e)
{
lastKey = e->text();
qDebug() << lastKey;
}
How can I make all widgets within this class use the same keyPressEvent?
You can solve your problem by installing event filters to every child of CustomDialog:
void CustomDialog::childEvent(QChildEvent *event)
{
if (event->added()) {
event->child()->installEventFilter(this);
}
}
bool CustomDialog::eventFilter(QObject *, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
keyPressEvent(static_cast<QKeyEvent*>(event));
return false;
}
But since every ignored keyPress event is sent to the parent widget, you can get keyPressEvent called multiple times for the same event.
I ended up deciding not to use keyPressEvent in this case for my purposes. I just needed to get the last key pressed in a QTextBrowser. Here is what I ended up doing:
connect(ui->textBrowser, SIGNAL(textChanged()), this, SLOT(handleTextBrowser()));
void CustomDialog::handleTextBrowser()
{
QTextCursor cursor(ui->textBrowser->textCursor());
QString key = ui->textBrowser->toPlainText().mid(cursor.position() - 1, 1);
qDebug() << key;
}

Qt: How do I handle the event of the user pressing the 'X' (close) button?

In Qt, what is the slot that corresponds to the event of the user clicking the 'X' (close) button of the window frame i.e. this button:
If there isn't a slot for this, is there any other way to trigger a function after the user presses the close button?
If you have a QMainWindow you can override closeEvent method.
#include <QCloseEvent>
void MainWindow::closeEvent (QCloseEvent *event)
{
QMessageBox::StandardButton resBtn = QMessageBox::question( this, APP_NAME,
tr("Are you sure?\n"),
QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
QMessageBox::Yes);
if (resBtn != QMessageBox::Yes) {
event->ignore();
} else {
event->accept();
}
}
If you're subclassing a QDialog, the closeEvent will not be called and so you have to override reject():
void MyDialog::reject()
{
QMessageBox::StandardButton resBtn = QMessageBox::Yes;
if (changes) {
resBtn = QMessageBox::question( this, APP_NAME,
tr("Are you sure?\n"),
QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
QMessageBox::Yes);
}
if (resBtn == QMessageBox::Yes) {
QDialog::reject();
}
}
Well, I got it. One way is to override the QWidget::closeEvent(QCloseEvent *event) method in your class definition and add your code into that function. Example:
class foo : public QMainWindow
{
Q_OBJECT
private:
void closeEvent(QCloseEvent *bar);
// ...
};
void foo::closeEvent(QCloseEvent *bar)
{
// Do something
bar->accept();
}
You can attach a SLOT to the
void aboutToQuit();
signal of your QApplication. This signal should be raised just before app closes.
also you can reimplement protected member QWidget::closeEvent()
void YourWidgetWithXButton::closeEvent(QCloseEvent *event)
{
// do what you need here
// then call parent's procedure
QWidget::closeEvent(event);
}

QComboBox EventFilter to popup

I have a little problem, I need to set my event filter to QComboBox popup.
I need to catch events when left and right keys are pressed.
How can I do this?
Thank you!
You need to set the eventFilter on QComboBox's view() (http://qt-project.org/doc/qt-4.8/qcombobox.html#view).
You may need to add following code somewhere in your code.
void MyComboBox::keyPressEvent (QKeyEvent *event)
{
if (event->button() == Qt::Key_Left)
{
// handle left key press
}
if (event->button() == Qt::Key_Right)
{
// handle right key press
}
}
Hope this helps!
The question is quite old, but I provide my answer since it can help someone else.
After popup all events will be sent to the list view used for the QComboBox popup. You can get the things done using key handler class watching on events for list view.
KeyPressHandler.h:
class KeyPressHandler : public QObject
{
Q_OBJECT
public:
explicit KeyPressHandler(QObject *parent = nullptr);
virtual ~KeyPressHandler() override;
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};
KeyPressHandler.cpp:
#include <QCoreApplication>
KeyPressHandler::KeyPressHandler(QObject *parent) : QObject(parent)
{
}
KeyPressHandler::~KeyPressHandler()
{
}
bool KeyPressHandler::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
switch(keyEvent->key())
{
case Qt::Key_Left:
// Send press event for the Key_Up which understood by list view
QCoreApplication::postEvent(obj, new QKeyEvent(QEvent::KeyPress,
Qt::Key_Up,
Qt::NoModifier));
return true;
case Qt::Key_Right:
QCoreApplication::postEvent(obj, new QKeyEvent(QEvent::KeyPress,
Qt::Key_Down,
Qt::NoModifier));
return true;
default:
break;
}
}
// standard event processing
return QObject::eventFilter(obj, event);
}
In ComboBox you will need to install event filter when popup is shown.
It can be done in different ways, for example by overriding QComboBox::showPopup() function.
MyComboBox.h:
#include <memory>
#include <QComboBox>
class MyComboBox : public QComboBox
{
Q_OBJECT
public:
explicit MyComboBox(QWidget *parent = 0);
protected:
void showPopup() override;
void hidePopup() override;
private:
std::unique_ptr<KeyPressHandler> m_key_press_handler;
};
MyComboBox.cpp:
...
void MyComboBox::showPopup()
{
if(!m_key_press_handler)
{
m_key_press_handler.reset(new KeyPressHandler());
QAbstractItemView *v = view();
v->installEventFilter(m_key_press_handler.get());
}
QComboBox::showPopup();
}
void MyComboBox::hidePopup()
{
m_key_press_handler.reset(nullptr);
QComboBox::hidePopup();
}