Calling function each time qt windows gain focus - c++

I have a mainwindow which in there is a Qtableview by clicking on insert record I go to other modal windows to add record when I add record and close the second windows I come back to main windows but the qtableview doesn't show the new record that is added. The record is in database.
I already make this somehow work with :
void MainWindow::showEvent( QShowEvent* event ) {
QWidget::showEvent( event );
updTbl();
}
But it only works when windows get minimized.

QMainWindow has also two event handler from QWidget
void QWidget::focusInEvent(QFocusEvent *event)
void QWidget::focusOutEvent(QFocusEvent *event)
If you use QtCreator, go to your mainwindow.h and search the line "class MainWindow : public QMainWindow". Right click on QMainWindow -> Refactoring -> Insert virtual function. That's an easy way to find which virtual functions exist and that can be overloaded, you can select focusInEvent and focusOutEvent from there.

Handling activate/deactivate events as follows will give you the desired behaviour
// overloading event(QEvent*) method of QMainWindow
bool MainWindow::event(QEvent* e)
{
switch (e->type())
{
case QEvent::WindowActivate:
// gained focus
//Update Table
break;
case QEvent::WindowDeactivate:
// lost focus
break;
};
return QMainWindow::event(e);
}
Ref: https://gist.github.com/01walid/2276009

Related

How to make perform many functions in mousepressevent

I want to make some functions on a dicom serie (with qt and vtk) , and I want to make some connections between the qt window and the mouse.
This is my primary design:
For example, if I click on zoombutton, then I click on my image with the left button of the mouse, I want that the image will be zoomed,
I know that we must use the function mousePressEvent but I have seen that we must use this name for any connection with the mouse, or I want to do 4 or 5 functions like this one, each one for one pushbutton.
How can I do this ?
As you suggested correctly, you should use mousePressEvent to capture a mouse press action. To perform the correct action on a mouse press (zoom, pan, ...), you should remember the last pressed button and call the appropriate method accordingly. This can be implemented as follows:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow ()
{
connect(ui->panButton, &QPushButton::clicked, this, &MainWindow::onPan)
connect(ui->zoomButton, &QPushButton::clicked, this, &MainWindow::onZoom)
...
}
protected slots:
enum Action {None, Pan, Zoom, ...};
void onPan () {currentAction = Pan;}
void onZoom () {currentAction = Zoom;}
protected:
void mousePressEvent(QMouseEvent *event)
{
switch(currentAction)
{
case Pan:
// perform Pan operation
break;
case Zoom:
// perform Zoom operation
break;
}
}
protected:
Action currentAction;
};

Does each QT widget have a 'show' signal?

I wanted to do some action when a dialog shows when it opens or when it maximizes from a minimal status or it moves from out of a screen.
Does QT have such a signal?
I am also not sure where to find if QT has a list of signals defined.
Does each QT widget have a 'show' signal?
If you look at Qt source code then you will find QWidget::show to be a slot:
public Q_SLOTS:
// Widget management functions
virtual void setVisible(bool visible);
void setHidden(bool hidden);
void show();
The slot is mainly for us, programmers to make us able to connect with signals for specific purposes like clicking the button we created does something to certain widget. As for Windows or Mac OS, we have the app serving all the events coming from the system via event loop. And QWidget reacts on all the 'signals' in the form of system events coming and yes, may, execute show() or showMaximized() or showMinimized slots then.
But I can assume you want to overload
virtual void showEvent(QShowEvent *);
virtual void hideEvent(QHideEvent *);
Like:
void MyWidget::showEvent(QShowEvent *e)
{
if (isMaximized())
{
if (e->spontaneous())
{
// the author would like to know
// if the event is issued by the system
}
; // the action for maximized
}
else
{
; // the action for normal show
}
}
void MyWidget::hideEvent(QHideEvent *)
{
if (isMinimized())
{
; // the action for minimized
}
else
{
; // the action for hide
}
}
For recognizing cases when the system operates the widget we can use QEvent::spontaneous().
Please also refer to show and hide event doc pages:
http://doc.qt.io/qt-5/qshowevent-members.html
http://doc.qt.io/qt-5/qhideevent.html

how to get touchevent for mainwindow in qt

I am writing an application for arm board. I have a mainwindow and I need to get the touch co-ordinates for single touch. Due to lack of Qt knowledge I am facing a problem of getting the touch event.
As per the QTouchEvent Class document, I have declared a slot as below.
#include <QTouchEvent>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(int x, int y, QWidget *parent = 0);
public slots:
void touchEvent(QTouchEvent *ev);
};
and in mainwindow.cpp I redefine it as below. The FFLabel[1] is already declared by me and I am writing it to confirm if the event is received.
void MainWindow::touchEvent(QTouchEvent *ev)
{
ui->FFLabel[1]->setText(QString("Event"));
switch (ev->type())
{
case QEvent::TouchBegin:
case QEvent::TouchEnd:
case QEvent::TouchUpdate:
{
}
}
}
I am not able to get the touchEvent. Can someone please help me.
I have verified the /dev/input/event2 and am receiving the event there.
QWidget has a number of protected virtual members, e.g., QWidget::mousePressEvent. They are called when the event occurs.
Usually one overrides such a function to run some code when a certain event happens.
The problem is, that, unlike for mouse press, there is no such virtual function QWidget::touchEvent (as of Qt 5.12). That is, you can't override it and it cannot be called when a touch event happens as QWidget is not aware of such a method.
C++11 introduced the override-keyword. If you had used it, you would have noticed that issue.
In order to receive touch events, you must override the more general QWidget::event method. Then filter for the events you're actually interested in:
bool MainWindow::event(QEvent* event)
{
switch (event->type()) {
case QEvent::TouchBegin:
qDebug() << "touch!";
return true;
default:
// call base implementation
return QMainWindow::event(event);
}
}
Note that you must state setAttribute(Qt::WA_AcceptTouchEvents); in order to receive any touch events (put it in the MainWindow-constructor).
You can read more details in the docs.
Events aren't slots. Declare it as a protected function.
protected:
void touchEvent(QTouchEvent *ev);
Edit: And you didn't put anything in your switch statement to show if you get the event.
void MainWindow::touchEvent(QTouchEvent *ev)
{
switch (ev->type())
{
case QEvent::TouchBegin:
ui->FFLabel[1]->setText("Event began.");
break;
case QEvent::TouchEnd:
ui->FFLabel[1]->setText("Event ended.");
break;
case QEvent::TouchUpdate:
{
ui->FFLabel[1]->setText("Event updated.");
break;
}
}
}
Edit: If it's still not working, it means your mainwindow isn't accepting touch events. You need to do this in your mainwindow's constructor:
setAttribute(Qt::WA_AcceptTouchEvents, true);
Disclaimer:
I had a similar issue and this is not a solution but may be a workaround depending on what you want to do.
In my case, the touch events were interpreted as mouse events so, MainWindow::touchEvent was never called but, the mouse events handler were.
I used MainWindow::mousePressEvent to get the touch point and MainWindow::mouseMoveEvent to get the drag.
This does not handle the multi-touch (it works for the separate contact points but you will have only one move event for all your points)
From Qt5.4, one may try (I didn't test as I'm stuck with Qt4), in the mouse events handler, to check the MouseEventSource If it's MouseEventSynthesizedBySystem it means from the documentation that:
the mouse event was synthesized from a touch event by the platform.
One can find more details checking this solution provided by Chirag Sachdeva in this post
And of course, with regards to the OP code, as user4516901 said, events aren't slots.

QDialog exec() and getting result value

I have subclassed QDialog to implement functionality similar to QMessageBox ( I needed this to allow for customization). It has a text message and OK, Cancel buttons. I am showing the dialog using exec() to make it blocking. Now, how do I return values of true/false when the user clicks on OK/Cancel?
I tried connecting the buttons to setResult() and then, return the result value when clicked, but
Clicking the buttons does not close the dialog box
the return value is incorrect.
Following is the code I have written. I think I am wrong in the exec/result part - but I am not sure how to fix it.
class MyMessageBox : public QDialog {
Q_OBJECT
private slots:
void onOKButtonClicked() { this->setResult(QDialog::Accepted); }
void onCancelButtonClicked() { this->setResult(QDialog::Rejected); }
public:
MyMessageBox(QMessageBox::Icon icon, const QString& title,
const QString& text, bool showCancelButton = true,
QWidget* parent = 0);
virtual void resizeEvent(QResizeEvent* e);
QDialog::DialogCode showYourself()
{
this->setWindowModality(Qt::ApplicationModal);
this->exec();
return static_cast<QDialog::DialogCode>(this->result());
}
};
The user will instantiate the class and call showYourself() which is expected to return the value and also close(and delete) the dialog.
I have posted partial code. Let me know if you need more and I will post the complete version.
Some points :
Rather than using setResult() yourself, use QDialog::accept() and QDialog::reject().
It seems you are not taking full advantage of the signals and slots. You need the object which create the dialog (or another one) to listen to the signals of the dialog.
In your code you are not connecting signals to slots either.
With my fix onOKButtonClicked and onCancelButtonClicked are unnecessary.
With my fix you don't need showYourself(). Just call exec and with the events
information will flow.
You need to add this code before showing the dialog (this assume it is in a dialog method):
QObject::connect(acceptButton, SIGNAL(clicked()), this, SLOT(accept()));
QObject::connect(rejectButton, SIGNAL(clicked()), this, SLOT(reject()));
In the caller object you have
void someInitFunctionOrConstructor(){
QObject::connect(mydialog, SIGNAL(finished (int)), this, SLOT(dialogIsFinished(int)));
}
void dialogIsFinished(int){ //this is a slot
if(result == QDialog::Accepted){
//do something
return
}
//do another thing
}
Another solution:
// set signal and slot for "Buttons"
connect(YesButton, SIGNAL(clicked()), dlg, SLOT(accept()));
connect(NoButton, SIGNAL(clicked()), dlg, SLOT(reject()));
// show modal window event loop and wait for button clicks
int dialogCode = dlg->exec();
// act on dialog return code
if(dialogCode == QDialog::Accepted) { // YesButton clicked }
if(dialogCode == QDialog::Rejected) { // NoButton clicked }
Case 1 Clicking the buttons does not close the dialog box.
For this you have to close the dialog on respective SLOTS, so Use
void onOKButtonClicked(){ this->setResult(QDialog::Accepted); this->close();}
void onCancelButtonClicked(){ this->setResult(QDialog::Rejected);this->close();}
Note: Only after you have clicked the Ok button or Cancel button in a standard QMessageBox, setResult() function is triggered and the status is changed. It's not the same effect when done vice versa.
Case 2 The return value is incorrect.
I think only after your dialog gets closed, you will have the result available in result() function. So I guess it will be solved, after you have made the changes specified in Case 1.
If it still persists, use your own private member function to resolve it.

Open only one instance of QDialog with show() , and also does the Object is deleted if i close the QDialog

in Qt im opening QDialog windows each time i click some item
im doing it with new , i like to be sure im opening only one instance of QDialog for each item
im clicking :
void foo::treeWidget_itemClicked(QTreeWidgetItem *item,nt column)
.....
QString groupID = item->data(0, Qt::UserRole).toString();
QString groupName = item->text(0);
GroupDialogContainer* pGroupDialogContainer = new GroupDialogContainer(groupID, groupName, this);
pGroupDialogContainer->show();
}
class GroupDialogContainer : public QDialog
{
Q_OBJECT
public:
GroupDialogContainer(QString GroupId,QString GroupName,QWidget *parent=0);
GroupDialogContainer(QWidget *parent=0);
virtual ~GroupDialogContainer();
Ui::GroupDialog ui;
public slots:
void closeEvent(QCloseEvent *event);
};
do i need to keep some kind of hash or vector of GroupDialogContainer ?
also my second question is :
does each time im closing the QDialog window with close () the object pGroupDialogContainer
that was responsible to open it is destroyer ed ? or do i need to delete it when im detecting that the QDIalog has closed?
Yes, you should probably keep some kind of list of your dialogs to keep track of which ones are already open. If your GroupID is your unique ID then you could do something like this:
QMap DialogMap;
void foo::treeWidget_itemClicked(QTreeWidgetItem *item,nt column)
{
.....
QString groupID = item->data(0, Qt::UserRole).toString();
if (! DialogMap.contains(groupID))
{
// Popup the dialog and add it to map
...
DialogMap.insert(groupID, pGroupDialogContainer);
}
}
Now, for the other part. The most important thing is that you need to remove the item from the map when the dialog closes. You could either delete the dialog then, or my suggestion would be to let the dialog delete itself when it closes - as follows:
// set automatic deletion of object on close
setAttribute(Qt::WA_DeleteOnClose);
But as I said, you'll still need to remove the dialog from the Map, or else you'll have a bad pointer in there, and your code will still think the dialog is open.
So you'll need some kind of signal from the dialog to indicate that it is closing. There is the finished(int result) signal, that is called when you trigger a result:
This signal is emitted when the
dialog's result code has been set,
either by the user or by calling
done(), accept(), or reject().
But, you can always create your own signal in your dialog, and emit it when the closeEvent is called in your dialog.
Then in the code that handles the map...
connect( pGroupDialogContainer, SIGNAL(WindowClosed()), this, SLOT(vCleanUpTheMap()));
...
void vCleanUpTheMap()
{
GroupDialogContainer *pDialog = dynamic_cast<GroupDialogContainer *>(sender());
if (pDialog)
{
// Just to keep things clean disconnect from the dialog.
disconnect(pDialog);
// I am assuming that you can get the key groupID from the dialog
// Cause it's a lot easier to remove from a map with the key
DialogMap.remove(pDialog->GetGroupID());
}
}
And that's it.