LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Blogs > rainbowsally
User Name
Password

Notices

Rate this Entry

QT4 Event preemption: mouse click to get object name

Posted 05-03-2012 at 11:30 AM by rainbowsally
Updated 09-04-2013 at 10:09 PM by rainbowsally

See also the experiment to dump properties.
http://www.linuxquestions.org/questi...nal-app-34716/

Now that we have event preemption ability, let's get simple again and create ui application that can tell the name of a widget by clicking on it.

[It's simpler than you think but I have uploaded the sources and makefile in case my description of this process is too complicated or confusing.]

Preemption for this is necessary because NORMAL mouse events need to be disabled (or consumed) during the call to identify the widgets.

So let's start here if we're using mc2.

Code:
mc2 -fetch qt4                         # makefile template for qt4
mc2 -create qt4-files src/click_id.ui  # generate initial fileset

# edit click_id.ui and change class from QWidget to QDialog
mc2 -run qt4-ui src                    # get ui: target and paste into mc2.def
mc2 -init                              # generate a self-updating makefile
Here's the ui file after editing and adding a few widgets for the test.

[The 'hints' tags have been stripped for size reduction... should still work even though the connection editor won't show them in the right places.]

file: src/click_id.ui
Code:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>click_id</class>
 <widget class="QDialog" name="click_id">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QPushButton" name="btnGetName">
   <property name="geometry">
    <rect>
     <x>280</x>
     <y>10</y>
     <width>102</width>
     <height>27</height>
    </rect>
   </property>
   <property name="text">
    <string>Get &amp;Name</string>
   </property>
  </widget>
  <widget class="QPushButton" name="btnQuit_1">
   <property name="geometry">
    <rect>
     <x>30</x>
     <y>220</y>
     <width>102</width>
     <height>27</height>
    </rect>
   </property>
   <property name="text">
    <string>Quit &amp;1</string>
   </property>
  </widget>
  <widget class="QPushButton" name="btnQuit_2">
   <property name="geometry">
    <rect>
     <x>150</x>
     <y>220</y>
     <width>102</width>
     <height>27</height>
    </rect>
   </property>
   <property name="text">
    <string>Quit &amp;2</string>
   </property>
  </widget>
  <widget class="QPushButton" name="btnQuit_3">
   <property name="geometry">
    <rect>
     <x>270</x>
     <y>220</y>
     <width>102</width>
     <height>27</height>
    </rect>
   </property>
   <property name="text">
    <string>Quit &amp;3</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>btnQuit_1</sender>
   <signal>clicked()</signal>
   <receiver>click_id</receiver>
   <slot>close()</slot>
  </connection>
  <connection>
   <sender>btnQuit_2</sender>
   <signal>clicked()</signal>
   <receiver>click_id</receiver>
   <slot>close()</slot>
  </connection>
  <connection>
   <sender>btnQuit_3</sender>
   <signal>clicked()</signal>
   <receiver>click_id</receiver>
   <slot>close()</slot>
  </connection>
  <connection>
   <sender>btnGetName</sender>
   <signal>clicked()</signal>
   <receiver>click_id</receiver>
   <slot>onGetID()</slot>
  </connection>
 </connections>
 <slots>
  <slot>onGetID()</slot>
 </slots>
</ui>
edit src/app-main.cpp so it looks like this.

file: src/app-main.cpp
Code:
#include <stdio.h>
#include <QtGui/QApplication>
#include "click_id.h"
#include "lqapp.h"

int main(int argc, char *argv[])
{
    LQApp a(argc, argv);
    click_id w;
    w.show();
    LQApp::watch = &w;
    return a.exec();
}

//////////////////////////////////////////////////////////////
// filling out LQApp

extern bool getting_id;

// user defined virtual function
bool LQApp::eventHandler(QObject* receiver, QEvent* event)
{
  if(event->type() == QEvent::MouseButtonPress)
  {
    if(getting_id)
    {
      // 1. find widget under mouse... well, that will be the intended 
      // receiver of the current event if getting_id is true.
      //
      // 2. get property of widget on mouse click and do NOT process 
      // this event.
      
      int indx;
      QVariant anytype;
      indx = receiver->metaObject()->indexOfProperty("objectName");
      if(indx < 0)
        printf("This baby has no 'objectName' property\n");
      else
      {
        const char* s;
        anytype = receiver->property("objectName");
        printf("objectName: %s\n", s = anytype.toByteArray());
      }
      indx = receiver->metaObject()->indexOfProperty("text");
      if(indx < 0)
        printf("This baby has no 'text' property\n");
      else
      {
        const char* s;
        anytype = receiver->property("text");
        printf("text: %s\n", s = anytype.toByteArray());
      }
      printf("\n");
      getting_id = false;
      return true; // consumed
    }
  }
  return QApplication::notify(receiver, event);
}

Edit click_id.h and add
Code:
public slots:
  void onGetID();
Edit click_id.cpp and add

Code:
bool getting_id;

void click_id::onGetID()
{
  getting_id = true;
}

We also need the subclassed QApplication that allows us to do this.

file: src/lqapp.cpp
Code:
// lqapp.cpp - preemptive event handling in subclass of QApplication

#include "lqapp.h"


// today the world, tomorrow the stars...
bool LQApp::notify(QObject *receiver, QEvent *event)
{ 
  // printf("receiver: %s0x%lX: eventType: %d\n", 
  //         receiver == watch ? "TARGET -> " : "", 
  //         (long)receiver, e->type());
  return eventHandler(receiver, event); // user defined virtual
}

LQApp::LQApp(int &argc, char **argv)
: QApplication(argc, argv)
{
  // additional setup
}

LQApp::~LQApp()
{
  // delete additional setup as req'd
}

QObject* LQApp::watch; // static, globally accessible
file: src/lqapp.h
Code:
// lqapp.h

#ifndef lqapp_h
#define lqapp_h

#include <QApplication>     // parent class
#include <qevent.h>           // always used

class LQApp : public QApplication
{
public:
  LQApp(int &argc, char **argv);
  ~LQApp();
  bool notify(QObject *receiver, QEvent *e);                // preemptive event handler
  virtual bool eventHandler(QObject *receiver, QEvent *e);  // let's try this approach
  static QObject* watch;                                    // ...
};

#endif // lqapp_h
Now we have
1. click_id.ui
2. main.cpp
3, 4. click_id.h and cpp (class declaration and slot definitions)
5, 6. lqapp.h and cpp (the event loop handler)

But we need two more files. If you're using qmake and a pro file, use uic and moc and qmake for this, or with mc2, here's how we can do it.

Code:
make ui
make
Here's the dump for my clicking on the middle button at the bottom, the form, and the "Get Name" button (that triggers the event preemption and printout) itself.

Code:
$> main
objectName: btnQuit_2
text: Quit &2

objectName: click_id
This baby has no 'text' property

objectName: btnGetName
text: Get &Name
And all of the buttons function normally if 'Get Name' is not clicked first. All three Quit buttons will indeed quit when we are not preempting the these events.

I'll upload a working copy of this experiment in case my description of the steps was too complicated.

The d/load is only about 6K.
http://rainbowsally.net/rainbowsally...lick-id.tar.gz
Type 'make'. Run 'main' from the terminal so you can see the dump.

Includes debug info in case you want to see how it works. (I use kdbg >= 5.0)

The Computer Mad Science Team

:-)
Posted in Uncategorized
Views 496 Comments 0
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 06:14 AM.

Main Menu
Advertisement

My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration