HOOPS/QT Integration Guide
Introduction
The following section explains how to build an application with the Qt GUI toolkit and the HOOPS 3D Application Framework. Compiling and linking is first reviewed, followed by a discussion of object relationships in the various components, and then an outline of programming steps needed to correctly create and initialize the objects and launch the Qt event loop.
Developers should start by compiling, linking and running the basic qt_simple application as the starting point for their application. It’s readable source code is located in the <hoops>/demo/qt/qt_simple directory of your HOOPS/3dAF installation while a Qt v4 variant is located in the <hoops>/demo/qt/qt_simple directory. Some familiarity with the Qt toolkit, HOOPS/3dGS and HOOPS/MVO is assumed.
Compiling and Linking
The Qt toolkit’s signals and slots mechanism requires that a pre-compilation step that builds special source files. The Qt Meta-Object Compiler (MOC), supplied as part of the Qt toolkit, must be used prior to the compilation step. Please refer to the Qt documentation for more information.
Compiler Definitions
The following definitions must be in place when compiling the HOOPS/Qt and HOOPS/MVO source code together:
General Definition
IS_QT // All HOOPS/Qt application
Window System Specific
IS_WIN // Applications built with HOOPS/Qt for MS Windows
IS_X11 // Applications built with HOOPS/Qt for UNIX
Using OpenGL on UNIX
USE_GLX_VISUAL // Applications built with HOOPS/Qt for UNIX that will use OpenGL; i.e., also IS_X11
Linking
The HOOPS/Qt Widget is supplied in clear source and should be added directly to the application’s source code base. Consequently there is no special HOOPS/Qt library to be linked in with the project.
Component Object Relationships
This section discusses the relationships between the objects in the various Qt and HOOPS/3dAF components. Building an application with both these toolkits minimally involves using the following objects from each component.
Qt
Only one QApplication
and at least QMainWindow
(or derived class)
HOOPS/Qt
At least one HQWidget
(you would typically create a custom widget derived from HQWidget
)
HOOPS/MVO
HBaseModel
, HBaseView
, an Operator
class derived from HBaseOperator
. Applications that want to implement selection of geometry will also need a HSelectionSet
object. These objects are all connected by private data members which store pointers to other objects in the following manner:
Steps to Building an Application with Qt and HOOPS
Programming with an object oriented GUI framework like Qt involves creating a set of objects, defining the ways in which they are connected, the manner in which they send and receive messages, and then launching the framework’s event loop. Building an application using Qt and the HOOPS/3dAF specifically requires the following steps in this order:
Creation and initialization of:
Creation and Initialization of Qt Objects
QApplication
For any GUI application that uses Qt, there is precisely one QApplication
object no matter how many windows the application has. It can be accessed via the global variable a
, declared in QApplication.h, which must be initialized prior to the creation of any other Qt objects. The qt_simple example performs this in the function main()
:
int main( int argc, char **argv )
{
...
// Create the one QApplication object
QApplication * a = new QApplication(argc,argv);
...
}
Color Allocation and GUI Style
The QApplication
object’s attributes for color allocation and GUI sytle must be configured. For Qt/HOOPS applications the color allocation must be set to “ManyColor”. The GUI Style is used to choose between Motif or Windows styles for the visual appearance and default behavior of the Qt GUI created.
Creation and Initialization of HOOPS/Qt Objects
HQApplication
One HQApplication
object should be created using the constructor that accepts a pointer to a Qt QApplication
object. The qt_simple exampleperforms this in the function main()
:
int main( int argc, char **argv )
{
...
if(argc == 2)
HQApplication * ha = new HQApplication(a, argv[1]);
else
HQApplication * ha = new HQApplication(a);
...
}
The HQApplication
object should create any Qt GUI object’s to be parented off of it during its initialization. The qt_simple example performs this when a HQApplication
object is being initialized by calling its private method HQApplication::load()
.
HQWidget
As many HQWidget
objects can be created as needed to implement the GUI’s design. These are more than likely going to be created by a constructor of a top level Qt widget like QMainWindow
or QDialog
. The qt_simple example performs this when an HQApplication
object is initialized by calling its private method HQApplication::load()
:
void HQApplication::load(const char * filename)
{
...
SimpleHQWidget * my_widget = new SimpleHQWidget(qframe, "SimpleHQWidget", filename);
...
}
HQDeleter
One global pointer must be declared and initialized in the application code block. The qt_simple example performs the global declaration in the file main.cpp and the initialization in the body of the function main()
:
// Create a global pointer to HOOPS/Qt class HQDeleter
HQDeleter * deleter=0;
int main( int argc, char **argv )
{
...
// Create an HQDeleter object and initialize the global pointer
deleter = new HQDeleter();
...
}
Creation and Initialization of HOOPS/MVO Objects
HDB
One global pointer to a HOOPS/MVO HDB object should be declared and initialized in the application’s main
function. The qt_simple example example:
int main( int argc, char **argv )
{
m_pHDB = new HDB();
m_pHDB->Init();
...
}
HBaseModel
Multiple HBaseModel
objects can be created as needed. The qt_simple example creates one for every SimpleHQWidget
object (i.e., there is a one-to-one mapping of HBaseModel to SimpleHQWidget objects) and does so in the SimpleHQWidget
constructor:
SimpleHQWidget::SimpleHQWidget(QWidget* parent, const char* name, const char * filename)
: HQWidget( parent, name )
{
m_pHBaseModel = new HBaseModel();
m_pHBaseModel->Init();
...
}
HBaseView
Multiple HBaseView
objects can be created as needed, with one object usually being created for each HQWidget
. The HBaseView
needs a valid window id and color map passed to its constructor on object creation; information used to connect a HOOPS/3dGS output driver instance to a Qt QWidget
. This requires that the QtWidget
, to which the HBaseView
will be attached, must already exist prior to creating the HBaseView
object.
The HBaseView
object should be created and initialized in an overloaded HQWidget::Init
method. This method is called by the base class HQWidget in its HQWidget::paintEvent
method the first time it is called, which first ensures that the widget is alive and thus the window ID is valid and the HBaseView
object can be created. Here is the qt_simple example:
void SimpleHQWidget::Init()
{
m_pHView = new HBaseView(m_pHBaseModel, NULL, NULL, NULL, GetWindowId(), GetColorMap(), GetClipOverride());
m_pHView->Init();
...
}
HBaseOperator
The HBaseView
class has a member HBaseView::m_pOperator
that is a pointer to an HBaseOperator
object. A default operator should be created during view initialization. The qt_simple example does this in the overloaded method of HQWidget::Init
:
void SimpleHQWidget::Init()
{
...
m_pHView->SetCurrentOperator(new HOpCameraOrbit(m_pHView));
...
}
HSelectionSet
Multiple HSelectionSet
object can be created as needed, but usually there is a one-to-one mapping of HSelectionSet
to HBaseView
objects.
The qt_simple example does not create a HSelectionSet
object because it does not provide any support for selection at this time.
Launching the Qt Event Loop
This is performed by calling the QApplication::exec()
method. Refer to the main()
function of the qt_simple example.