QT/c++ How to check globaly is mouse press or release? - c++

void MainWindow::mousePressEvent(QMouseEvent* event)
{
if(event->button() == Qt::LeftButton)
{
timer->start(timer_time);
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent* event)
{
if(event->button() == Qt::LeftButton)
{
timer->stop();
}
}
This code works when i use it inside my appliacation, but if I want use it outside it won't be working. How can I do this?
It should start timer when LeftButton is pressed and stop when LeftButton release.
SOLUTION: understanding-the-low-level-mouse-and-keyboard-hook-win32

It sounds like hooks are what you're looking for.
Basically, hooks let you interact with the activity within your system, and can be used alter its behavior.
The event listeners in your code will only catch the mouse events that your OS delegates to your QT application. This is why your code only works when you use it inside your application. Using hooks, you can intercept mouse events at a system level and have them handled them in your app instead of letting the OS decide where they should be handled.
Here's what to use to set them up, and here's a little guide on the implementation details.

Related

Qt Mac - App not restoring after closing

In Mac when we press the close button apps by default hide to dock. The same happens with my Qt app too, but it does not restore afterwards as expected. There are many posts which provide code to detect click on dock icon.
I don't need to detect, I just want the default functionality, that it should restore.
It restores if I minimize but not on close.
The fix I used is:
void myAPP::closeEvent(QCloseEvent *event)
{
#ifdef Q_OS_MAC
event->ignore();
this->setWindowState(Qt::WindowMinimized) ;
return;
#endif
}
It makes it minimize on close and than my app restores properly. But now the issue is that it is preventing shutdown on Mac unless I exit the application. Shutdown makes the app minimize.
I am using Qt 5.4
To fix the issue, I wanted to know the source of Close Event. If source is user than minimize, else if source is OS shutdown event than exit.
We can use event->spontaneous() to check that. Following is the working solution:
void myAPP::closeEvent(QCloseEvent *event)
{
#ifdef Q_OS_MAC
if(event->spontaneous())
{
event->ignore();
this->setWindowState(Qt::WindowMinimized) ;
return;
}
#endif
}

Qt or any other lang. Event Loop

I'm a c++ programmer on Qt platform.
I'm wondering, how does the event loop "knows" to which widget to send an event, mainly mouse/keyboard events?
Is it done based on mouse coordinates and z-order?
What about events from keyboard?
Thanks
The event loop doesn't know. This is done in other bits of code.
The term you're looking for with the keyboard is "focus". Exactly one window has focus, systemwide (or at least one window per keyboard on multi-user systems). The OS delivers the keystrokes to that window. Qt just finds the Qt object from the native window handle. Similarly, mouse clicks are mostly handled by the OS.
It doesn't know.
When you want to capture an event, you must create an event filter that either captures the event, or allows it to be passed down.
Here's a very simple event filter that I created some time ago:
bool OGL_widget::eventFilter(QObject *obj, QEvent *event) {
switch (event->type()) {
case QEvent::KeyRelease:
case QEvent::KeyPress: {
QKeyEvent *key = static_cast<QKeyEvent*> (event);
if (!key->isAutoRepeat())
key_event_queue << *key;
}
break;
case 1001:
case 1002: {
Savestate_event *save = static_cast<Savestate_event*> (event);
save_event_queue << *save;
}
break;
}
return QObject::eventFilter(obj, event);
}
Take a look at this well written article of events at Qt docs.

How to keep the application running when the last window is closed?

I'm working on a very basic GUI project in Qt (using c++) and want to be able to close the main window in my program without the program quitting all the way. By default, it will exit when the main window is closed. How to prevent that?
Set the QApplication::quitOnLastWindowClosed property to false:
qApp->setQuitOnLastWindowClosed(false);
If you still need your window to exist, you would probably like to reimplement your closeEvent method like this:
void MainWindow::closeEvent(QCloseEvent *event)
{
hide();
event->ignore();
}
or use QGuiApplication::setQuitOnLastWindowClosed(false)
If you want to perform some pre-exit operation as saving settings, connect some slot doing what you want to QCoreApplication::aboutToQuit()

Checking if any other button was clicked

I tried to find answer, but I didn't find it.
I want to do something like this:
when I click button, I would like it to repeat actions till another button is clicked
I have something like this:
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
if(pole!=NULL){
pole->przesun_lidera(pole->wladca);
pole->rozstaw();
pole->rysuj_plansze();
}
}
and I want to repeat actions within "if", until I click another button.
Could someone tell me, how can I achieve this?
I think you have two possibilities here. One is to make a thread and execute your code in it until a condition, set by another button is set. Another possibility is to allow the message pump to process messages while inside the loop, by calling ProcessMessages(), e.g.
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
condition = false;
while( !condition && pole!=NULL){
pole->przesun_lidera(pole->wladca);
pole->rozstaw();
pole->rysuj_plansze();
Application->ProcessMessages();
Sleep(1); // don't be a processor hog
}
}
void __fastcall TForm1::BitBtn2Click(TObject *Sender)
{
condition = true;
}
You will need to have a function that is executed in the "background".
Windows is an event driven system. Your functions are only activated when Windows receives an event. My understanding is that you want something to happen while waiting for a specific event (button press) to occur. This time between events is "background" time.
One idea is to have Windows execute your function while it is waiting. Search the web for "Windows spin wait". This will give you information on how to "hook" a function to the background or spin-wait loop.
You may also want to create another thread as a background task. Have your first button click turn on the background thread. The background thread will execute until a semaphore or wait-object is set. The second button press will set this semaphore / wait-object, informing the background task to stop. There are similar methods, but this is the foundation of the issue.

Qt Application: Simulating modal behaviour (enable/disable user input)

I am currently working on an application that launches separate processes which display additional dialogs. The feature I am trying to implement is simulating modal behavior of these dialogs. More specifically, I need the application to stop processing all input, both mouse and keyboard, when the dialog is launched, and resume when it's closed.
It is not so important for the dialog to remain on top of the application, although if you can suggest how to do that without resorting to Always-On-Top behavior, that would be nice as well.
To note, the application is compiled under both Windows and Linux. Also, it is not an option to launch the dialogs directly. They are in separate executables. Also the application is a pretty complex piece of software, so disabling widgets individually is not an option, or at least a not very viable one.
I found lock() and unlock() functions in QApplication class in Qt 3.3. We are currently using Qt 4.5, which doesn't seem to have that API. As a matter of fact, Qt 4.5 QApplication class doesn't seem to provide access to the Event Loop either.
To summarize: How do I disable/enable user input in a Qt Application, both mouse and keyboard shortcuts?
gj already proposed this solution but I thought I'd paste my implementation just for reference:
Implement a filter class that will absorb user input actions.
class BusyAppFilter : public QObject
{
protected:
bool eventFilter( QObject *obj, QEvent *event );
};
bool BusyAppFilter::eventFilter(QObject *obj, QEvent *event)
{
switch ( event->type() )
{
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::MouseButtonPress:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
case QEvent::HoverEnter:
case QEvent::HoverLeave:
case QEvent::HoverMove:
case QEvent::DragEnter:
case QEvent::DragLeave:
case QEvent::DragMove:
case QEvent::Drop:
return true;
default:
return QObject::eventFilter( obj, event );
}
}
Then place this code your QApplication class:
QCursor busyCursor( Qt::WaitCursor );
setOverrideCursor( busyCursor );
BusyAppFilter filter;
installEventFilter( &filter ) ;
//... do the process stuff ...
removeEventFilter( &filter );
restoreOverrideCursor();
To get full access to the application wide events, use QObject::installEventFilter() or QCoreApplication::setEventFilter() on your application object.
If your filter function returns true, Qt stops further processing of the event.
To not get too platform specific with the forwarding of the events to your other applications, i'd go for a suitable IPC mechanism.
As an alternative answer, you can create your own event loop and start running it if necessary. You would need to create a QEventLoop object, connect a signal from another process to its quit() slot (such as from a QProcess that you are running your other program in), then exec() the loop. If I read things correctly, nothing will be handled by your main event loop while that loop is running.