Sophie

Sophie

distrib > Fedora > 15 > i386 > by-pkgid > ab972abb34adf97ebe2e94ab6b5a0050 > files > 34

HippoDraw-1.21.1-14.fc15.i686.rpm

<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>HippoDraw Documenation</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
<link rel="shortcut icon" href="lib/hippoApp.ico">
</head><body>
<!-- Generated by Doxygen 1.7.3 -->
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Main&#160;Page</span></a></li>
      <li class="current"><a href="pages.html"><span>Related&#160;Pages</span></a></li>
    </ul>
  </div>
</div>
<div class="header">
  <div class="headertitle">
<h1>Building custom applications with C++ </h1>  </div>
</div>
<div class="contents">
<div class="textblock"><p>One can build custom applications with <b>HippoDraw's</b> C++ class library along with Qt.</p>
<h2><a class="anchor" id="customapps_canvas"></a>
Custom application with canvas</h2>
<p>To build an application with the CanvasWindow and Inspector, it can be as simple as the one shown below...</p>
<div class="fragment"><pre class="fragment"><span class="preprocessor">#include &quot;QtApp.h&quot;</span>

<span class="keywordtype">int</span> main ( <span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>** argv)
{
  QtApp app ( argc, argv );
  app.setFirstWindow();
  
  <span class="keywordflow">return</span> app.exec();
}
</pre></div><p>Your custom code, say to generate the <a class="el" href="ntuple_root.html">data source</a> data should be inserted before the call to <code>app.exec()</code> as that function starts the Qt event loop and doesn't return until the application is terminated.</p>
<p>If you already have a Qt application, then you can add the <b><b>HippoDraw</b> CanvasWindow</b> and <b>Inspector</b> to your application by adding code to your main with something like the implementation of QtApp::setFirstWindow does. The result might look like this ...</p>
<div class="fragment"><pre class="fragment"><span class="preprocessor">#include &quot;qt/CanvasWindow.h&quot;</span>
<span class="preprocessor">#include &quot;qapplication.h&quot;</span>


<span class="keywordtype">int</span> main ( <span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>** argv)
{
  MyApp app ( argc, argv );
  
  CanvasWindow * window = <span class="keyword">new</span> CanvasWindow ();
  window-&gt;show();

  <span class="keywordflow">return</span> app.exec();
}
</pre></div><p>One doesn't need to create the CanvasWindow before starting the Qt event loop. It can be created at any time.</p>
<h2><a class="anchor" id="customapps_widget"></a>
Custom application with widget in window</h2>
<p>This section describes how to put a <b>HippoDraw</b> plot in a single window.</p>
<p>First the QApplication object is created and the NTupleController is used to create an NTuple by reading a file as shown here.</p>
<div class="fragment"><pre class="fragment"><span class="keywordtype">int</span> main ( <span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv )
{
    QApplication app ( argc, argv );

    <span class="keyword">const</span> <span class="keywordtype">string</span> filename ( <span class="stringliteral">&quot;../../../hippodraw/examples/aptuple.tnt&quot;</span> );
    NTupleController * nt_controller = NTupleController::instance ();
    NTuple * nt 
      = nt_controller-&gt;createNTuple ( filename  );
</pre></div><p>In a custom application, you will probably have other ways of creating the NTuple. If you want the NTuple visible to the Inspector, then you must register it with the NTupleController like this ...</p>
<div class="fragment"><pre class="fragment">    NTuple * nt = <span class="comment">// create your NTuple somehow </span>
    NTupleController * nt_controller = NTupleController::instance ();

    nt_controller-&gt;registerNTuple ( nt );
</pre></div><p>Next a display is created bound to the NTuple and one of its columns.</p>
<div class="fragment"><pre class="fragment">    <span class="keyword">const</span> <span class="keywordtype">string</span> histo ( <span class="stringliteral">&quot;Histogram&quot;</span> );
    vector &lt; string &gt; bindings;
    bindings.push_back ( <span class="stringliteral">&quot;Cost&quot;</span> );

    DisplayController * dc_controller = DisplayController::instance ();
    PlotterBase * plotter 
      = dc_controller-&gt;createDisplay ( histo, *nt, bindings );
</pre></div><p>Note that DisplayController creates the appropriate class derived from PlotterBase for the kind of display you requested.</p>
<p>Plotter objects are used both for canvas items and widgets. In this case, a QtViewWidget is created and the plotter is attached to it.</p>
<div class="fragment"><pre class="fragment">    QtViewWidget * view = <span class="keyword">new</span> QtViewWidget ( );
    view-&gt;setPlotter ( plotter );
</pre></div><p>Finally, the view it set into the Qt main window, resized, captioned, and the event loop started.</p>
<div class="fragment"><pre class="fragment">    view-&gt;resize ( 200, 200 );
    app.setMainWidget( view );
    view-&gt;setCaption ( <span class="stringliteral">&quot;Qt HippoDraw - View widget&quot;</span> );
    view-&gt;show();

    <span class="keywordtype">int</span> result = a.exec();
</pre></div><p>Note that the above code used methods that QtViewWidget inherits from Qt's QWidget class.</p>
<p>Don't forget to clean up when you are done.</p>
<div class="fragment"><pre class="fragment">    <span class="keyword">delete</span> view;
    <span class="keyword">delete</span> nt;

    <span class="keywordflow">return</span> result;
}
</pre></div><p>The resulting application window looks like this ...</p>
<div align="center">
<img src="widget_window.png" alt="widget_window.png"/>
<p><strong>QtViewWidget set as application's main window.</strong></p></div>
 <p>The complete code is shown below ...</p>
<div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 
<a name="l00007"></a>00007 <span class="preprocessor">#include &quot;qt/QtViewWidget.h&quot;</span>
<a name="l00008"></a>00008 
<a name="l00009"></a>00009 <span class="preprocessor">#include &quot;controllers/DisplayController.h&quot;</span>
<a name="l00010"></a>00010 <span class="preprocessor">#include &quot;datasrcs/NTupleController.h&quot;</span>
<a name="l00011"></a>00011 <span class="preprocessor">#include &quot;datasrcs/NTuple.h&quot;</span>
<a name="l00012"></a>00012 <span class="preprocessor">#include &quot;plotters/PlotterBase.h&quot;</span>
<a name="l00013"></a>00013 
<a name="l00014"></a>00014 <span class="preprocessor">#include &lt;qapplication.h&gt;</span>
<a name="l00015"></a>00015 
<a name="l00016"></a>00016 <span class="preprocessor">#include &lt;string&gt;</span>
<a name="l00017"></a>00017 <span class="preprocessor">#include &lt;vector&gt;</span>
<a name="l00018"></a>00018 
<a name="l00019"></a>00019 <span class="keyword">using</span> std::string;
<a name="l00020"></a>00020 <span class="keyword">using</span> std::vector;
<a name="l00021"></a>00021 
<a name="l00022"></a>00022 
<a name="l00030"></a>00030 <span class="keyword">using namespace </span>hippodraw;
<a name="l00031"></a>00031 
<a name="l00032"></a>00032 <span class="keywordtype">int</span> main ( <span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> **argv )
<a name="l00033"></a>00033 {
<a name="l00034"></a>00034     QApplication a( argc, argv );
<a name="l00035"></a>00035 
<a name="l00036"></a>00036     <span class="keyword">const</span> <span class="keywordtype">string</span> filename ( <span class="stringliteral">&quot;../../../hippodraw/examples/aptuple.tnt&quot;</span> );
<a name="l00037"></a>00037     NTupleController * nt_controller = NTupleController::instance ();
<a name="l00038"></a>00038     DataSource * nt 
<a name="l00039"></a>00039       = nt_controller-&gt;createNTuple ( filename  );
<a name="l00040"></a>00040 
<a name="l00041"></a>00041     <span class="keyword">const</span> <span class="keywordtype">string</span> histo ( <span class="stringliteral">&quot;Histogram&quot;</span> );
<a name="l00042"></a>00042     vector &lt; string &gt; bindings;
<a name="l00043"></a>00043     bindings.push_back ( <span class="stringliteral">&quot;Cost&quot;</span> );
<a name="l00044"></a>00044 
<a name="l00045"></a>00045     DisplayController * dc_controller = DisplayController::instance ();
<a name="l00046"></a>00046     PlotterBase * plotter 
<a name="l00047"></a>00047       = dc_controller-&gt;createDisplay ( histo, *nt, bindings );
<a name="l00048"></a>00048 
<a name="l00049"></a>00049     QtViewWidget * view = <span class="keyword">new</span> QtViewWidget ( );
<a name="l00050"></a>00050     view-&gt;setPlotter ( plotter );
<a name="l00051"></a>00051 
<a name="l00052"></a>00052     view-&gt;resize ( 200, 200 );
<a name="l00053"></a>00053     a.setMainWidget( view );
<a name="l00054"></a>00054     view-&gt;setCaption ( <span class="stringliteral">&quot;Qt HippoDraw - View widget&quot;</span> );
<a name="l00055"></a>00055     view-&gt;show();
<a name="l00056"></a>00056 
<a name="l00057"></a>00057     <span class="keywordtype">int</span> result = a.exec();
<a name="l00058"></a>00058 
<a name="l00059"></a>00059     <span class="keyword">delete</span> view;
<a name="l00060"></a>00060     <span class="keyword">delete</span> nt;
<a name="l00061"></a>00061 
<a name="l00062"></a>00062     <span class="keywordflow">return</span> result;
<a name="l00063"></a>00063 }
</pre></div><h2><a class="anchor" id="customapps_window"></a>
Custom application with custom widget in Qt Designer</h2>
<p>One can use <b>HippoDraw's</b> QtViewWidget as a custom widget within Qt Designer. When doing so, your main program may look like this</p>
<div class="fragment"><pre class="fragment"><span class="preprocessor">#include &lt;qapplication.h&gt;</span>
<span class="preprocessor">#include &quot;QtViewWidgetWindow.h&quot;</span>

<span class="keywordtype">int</span> main( <span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> ** argv )
{
    QApplication app ( argc, argv );
    QtViewWidgetWindow w;
    w.show();
    app.connect( &amp;a, SIGNAL( lastWindowClosed() ), &amp;a, SLOT( quit() ) );

    <span class="keywordflow">return</span> app.exec();
}
</pre></div><p>In this example, the class QtViewWidgetWindow was built with Qt Designer. It was created by asking for a new main window. QtViewWidget was inserted in Qt Designer as a custom widget. The results look like this ...</p>
<div align="center">
<img src="custom_widget_designer.png" alt="custom_widget_designer.png"/>
<p><strong>QtViewWidget as custom widget</strong></p></div>
 <p>In this example, the fileOpen() slot as implemented like the implementation in the <a class="el" href="customapps_cplusplus.html#customapps_canvas">Custom application with canvas</a> example. But in addition, the implementation creates an Inspector and signals it to update itself with the created plotter. The code look like this ...</p>
<div class="fragment"><pre class="fragment">  m_inspector = <span class="keyword">new</span> Inspector ();
  m_inspector-&gt;show();
  QCustomEvent * <span class="keyword">event</span> = <span class="keyword">new</span> QCustomEvent ( QEvent::User, plotter );
  QApplication::postEvent ( m_inspector, event );
</pre></div><p>One might have expected a direct call to Inspector::update following the Observer pattern instead of this implementation. However, it was found that under the Windows operating system, such a direct call caused problems with the OS's threading model. So the QCustomEvent is used to avoid the problem.</p>
<p>Some part of the application may cause a change to the plotter. When that happens, one needs to update the Inspector. Following the Observer pattern, when something in the plotter changes, it sends an update message to its observer which is the QtViewWidget. It in turn, needs to send a message to its parent which is the QtViewWidgetWindow object. It uses a QCustomEvent to do this, so the implementation of the QtViewWidgetWindow must implement it something like this ...</p>
<div class="fragment"><pre class="fragment"><span class="keywordtype">void</span> QtViewWidgetWindow::customEvent ( QCustomEvent * event )
{
  <span class="keywordtype">void</span> * data = <span class="keyword">event</span>-&gt;data();
  QCustomEvent * e = <span class="keyword">new</span> QCustomEvent ( QEvent::User, data );

  QApplication::postEvent ( m_inspector, e );
}
</pre></div><p>After opening the file, the window looks like this ...</p>
<div align="center">
<img src="custom_window.png" alt="custom_window.png"/>
<p><strong>QtViewWidgetWindow after opening file</strong></p></div>
 <p>The complete source code is show below ...</p>
<div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/* -*- mode: c++ -*- */</span>
<a name="l00002"></a>00002 <span class="comment">/****************************************************************************</span>
<a name="l00003"></a>00003 <span class="comment">** ui.h extension file, included from the uic-generated form implementation.</span>
<a name="l00004"></a>00004 <span class="comment">**</span>
<a name="l00005"></a>00005 <span class="comment">** If you wish to add, delete or rename functions or slots use</span>
<a name="l00006"></a>00006 <span class="comment">** Qt Designer which will update this file, preserving your code. Create an</span>
<a name="l00007"></a>00007 <span class="comment">** init() function in place of a constructor, and a destroy() function in</span>
<a name="l00008"></a>00008 <span class="comment">** place of a destructor.</span>
<a name="l00009"></a>00009 <span class="comment">*****************************************************************************/</span>
<a name="l00010"></a>00010 
<a name="l00011"></a>00011 <span class="keyword">using</span> std::string;
<a name="l00012"></a>00012 <span class="keyword">using</span> std::vector;
<a name="l00013"></a>00013 
<a name="l00014"></a>00014 <span class="keyword">using namespace </span>hippodraw;
<a name="l00015"></a>00015 
<a name="l00018"></a>00018 <span class="keywordtype">void</span> QtViewWidgetWindow::init()
<a name="l00019"></a>00019 {
<a name="l00020"></a>00020 
<a name="l00021"></a>00021 }
<a name="l00022"></a>00022 
<a name="l00023"></a>00023 <span class="keywordtype">void</span> QtViewWidgetWindow::fileOpen()
<a name="l00024"></a>00024 {
<a name="l00025"></a>00025 <span class="preprocessor">#if QT_VERSION &lt; 0x040000 // 3.1.0</span>
<a name="l00026"></a>00026 <span class="preprocessor"></span>   QString file_name 
<a name="l00027"></a>00027     = QFileDialog::getOpenFileName ( QString::null, <span class="comment">// starting directory</span>
<a name="l00028"></a>00028                                      <span class="stringliteral">&quot;ntuple (*.*)&quot;</span>, <span class="comment">// filter</span>
<a name="l00029"></a>00029                                      <span class="keyword">this</span>, <span class="comment">// parent</span>
<a name="l00030"></a>00030                                      <span class="stringliteral">&quot;open ntuple file&quot;</span>, <span class="comment">// internal name</span>
<a name="l00031"></a>00031                                      <span class="stringliteral">&quot;Open ntuple&quot;</span> ); <span class="comment">// actual window caption</span>
<a name="l00032"></a>00032 <span class="preprocessor">#else</span>
<a name="l00033"></a>00033 <span class="preprocessor"></span>   QString file_name 
<a name="l00034"></a>00034     = Q3FileDialog::getOpenFileName ( QString::null, <span class="comment">// starting directory</span>
<a name="l00035"></a>00035                                      <span class="stringliteral">&quot;ntuple (*.*)&quot;</span>, <span class="comment">// filter</span>
<a name="l00036"></a>00036                                      <span class="keyword">this</span>, <span class="comment">// parent</span>
<a name="l00037"></a>00037                                      <span class="stringliteral">&quot;open ntuple file&quot;</span>, <span class="comment">// internal name</span>
<a name="l00038"></a>00038                                      <span class="stringliteral">&quot;Open ntuple&quot;</span> ); <span class="comment">// actual window caption</span>
<a name="l00039"></a>00039 <span class="preprocessor">#endif</span>
<a name="l00040"></a>00040 <span class="preprocessor"></span>  <span class="keywordflow">if</span> ( file_name.isEmpty () ) <span class="keywordflow">return</span>;
<a name="l00041"></a>00041 
<a name="l00042"></a>00042 <span class="preprocessor">#if QT_VERSION &lt; 0x030100 // 3.1.0</span>
<a name="l00043"></a>00043 <span class="preprocessor"></span>  <span class="keyword">const</span> <span class="keywordtype">string</span> filename ( file_name );  
<a name="l00044"></a>00044 <span class="preprocessor">#else</span>
<a name="l00045"></a>00045 <span class="preprocessor"></span>  <span class="keyword">const</span> <span class="keywordtype">string</span> filename( file_name.latin1() );
<a name="l00046"></a>00046 <span class="preprocessor">#endif</span>
<a name="l00047"></a>00047 <span class="preprocessor"></span> NTupleController * nt_controller = NTupleController::instance ();
<a name="l00048"></a>00048  DataSource * nt 
<a name="l00049"></a>00049     = nt_controller-&gt;createNTuple ( filename  );
<a name="l00050"></a>00050 
<a name="l00051"></a>00051   <span class="keyword">const</span> <span class="keywordtype">string</span> histo ( <span class="stringliteral">&quot;Histogram&quot;</span> );
<a name="l00052"></a>00052   vector &lt; string &gt; bindings;
<a name="l00053"></a>00053   bindings.push_back ( <span class="stringliteral">&quot;Cost&quot;</span> );
<a name="l00054"></a>00054 
<a name="l00055"></a>00055   DisplayController * dc_controller = DisplayController::instance ();
<a name="l00056"></a>00056   PlotterBase * plotter 
<a name="l00057"></a>00057       = dc_controller-&gt;createDisplay ( histo, *nt, bindings );
<a name="l00058"></a>00058 
<a name="l00059"></a>00059   m_view-&gt;setPlotter ( plotter );
<a name="l00060"></a>00060 
<a name="l00061"></a>00061   m_inspector = <span class="keyword">new</span> Inspector ();
<a name="l00062"></a>00062   m_view -&gt; setInspector ( m_inspector );
<a name="l00063"></a>00063 
<a name="l00064"></a>00064   m_inspector-&gt;show();
<a name="l00065"></a>00065   m_view-&gt;update ( plotter );
<a name="l00066"></a>00066   PlotterEvent * <span class="keyword">event</span> = <span class="keyword">new</span> PlotterEvent ( plotter );
<a name="l00067"></a>00067   QApplication::postEvent ( m_inspector, event );
<a name="l00068"></a>00068 }
<a name="l00069"></a>00069 
<a name="l00070"></a>00070 <span class="keywordtype">void</span> QtViewWidgetWindow::filePrint()
<a name="l00071"></a>00071 {
<a name="l00072"></a>00072 
<a name="l00073"></a>00073 }
<a name="l00074"></a>00074 
<a name="l00075"></a>00075 <span class="keywordtype">void</span> QtViewWidgetWindow::fileExit()
<a name="l00076"></a>00076 {
<a name="l00077"></a>00077 qApp-&gt;quit();
<a name="l00078"></a>00078 }
<a name="l00079"></a>00079 
<a name="l00080"></a>00080 <span class="keywordtype">void</span> QtViewWidgetWindow::helpAbout()
<a name="l00081"></a>00081 {
<a name="l00082"></a>00082 
<a name="l00083"></a>00083 }
</pre></div> </div></div>
<hr size="1"><address style="align: right;"><small>
Generated for HippoDraw by <a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0>
</a> </small></address>
</body>
</html>