How to embeed a view on an QtWidget ( Qt5) - Problem with WinId() - Please Help me

Hello,

I'm pretty new on opencascade and I'm having troubles on setting a OCC view into a Qt window.

I Tried the code suggested according to release notes of version OCC6.6.0, but There is a problem with WinId() function.
The problem is that I get an error compiling this.
I'm using Opencascade 6.6.0 , Qt5 and MS Visual Studio 2012.
see:

error C2664: 'WNT_Window::WNT_Window(const Aspect_Handle,const Quantity_NameOfColor)' : cannot convert parameter 1 from 'WId' to 'const Aspect_Handle'
1> Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1> Generating Code...

See below the code I'm using:

Handle(Graphic3d_GraphicDriver) aGraphicDriver = new OpenGl_GraphicDriver ("TKOpenGl");
aGraphicDriver->Begin (new Aspect_DisplayConnection());
TCollection_ExtendedString aNameOfViewer ("Visu3D");
Handle(V3d_Viewer) aViewer = new V3d_Viewer (aGraphicDriver, aNameOfViewer.ToExtString());
aViewer->Init();

Aspect_Handle aWindowHandle = (Aspect_Handle )winId();
Handle(WNT_Window) aWindow = new WNT_Window (winId());

Handle(V3d_View) aView = aViewer->CreateView();
aView->SetWindow (aWindow);

Thorsten H's picture

Hi,

try this...

int windowHandle = (int) winId();
short hi, lo;
lo = (short) windowHandle;
hi = (short) (windowHandle >> 16);
#ifdef WNT
Handle(WNT_Window) hWnd = new WNT_Window(
Handle(Graphic3d_WNTGraphicDevice)::DownCast(m_Context->CurrentViewer()->Device()),
(int) hi,
(int) lo);
hWnd->SetFlags( WDF_NOERASEBKGRND );
#else
Handle(Xw_Window) hWnd = new Xw_Window(Handle(Graphic3d_GraphicDevice)::DownCast(context->CurrentViewer()->Device()),(int) hi,(int) lo,Xw_WQ_SAMEQUALITY);
#endif // WNT

m_V3DView->SetWindow( hWnd );

if ( !hWnd->IsMapped() ){
hWnd->Map();
}
}

Thorsten

marcelo.fontes's picture

Hello Thorsten, thank you for the reply.

in OCC6.6.0, the command "Graphic3d_GraphicDevice" is not available anymore, according to the release notes.
I tried to mix the code with your sugestion. I can compile it, but it crashes at the command " Map()".
see below:

int windowHandle = (int) winId();

Handle(Graphic3d_GraphicDriver) aGraphicDriver = new OpenGl_GraphicDriver ("TKOpenGl");
aGraphicDriver->Begin (new Aspect_DisplayConnection());
TCollection_ExtendedString aNameOfViewer ("Visu3D");
Handle(V3d_Viewer) aViewer= new V3d_Viewer (aGraphicDriver, aNameOfViewer.ToExtString());

aViewer->Init();
aViewer->SetDefaultLights();
aViewer->SetLightOn();

Aspect_Handle aWindowHandle = (Aspect_Handle) windowHandle;

Handle (WNT_Window) aWindow = new WNT_Window(windowHandle,Quantity_NOC_MATRAGRAY);

// setup the window for a new view

Handle(V3d_View) aView = aViewer->CreateView();
aView->SetWindow (aWindow);

if (!aWindow->IsMapped()) <----- IT CRASHES HERE
{
aWindow->Map();
}

myAISContext =new AIS_InteractiveContext(aViewer);

Handle(V3d_Viewer) myViewer = aViewer;
Handle(AIS_InteractiveContext) aContext;
aContext = new AIS_InteractiveContext(myViewer);

BRepPrimAPI_MakeSphere S(gp_Pnt(0,300,0), 100.);
Handle(AIS_Shape) aisthing=new AIS_Shape(S.Shape());
aContext->SetDisplayMode(aisthing,AIS_Shaded);
aContext->Display(aisthing);
aContext->DisplayAll();
aView->MustBeResized();
aView->Redraw();

//////////////////////////////////////////////

however, if I replace the Code above by this one, I can Compile but it does not show any drawing on the form.

Handle(Graphic3d_GraphicDriver) aGraphicDriver = new OpenGl_GraphicDriver ("TKOpenGl");
aGraphicDriver->Begin (new Aspect_DisplayConnection());
TCollection_ExtendedString aNameOfViewer ("Visu3D");
Handle(V3d_Viewer) aViewer= new V3d_Viewer (aGraphicDriver, aNameOfViewer.ToExtString());

aViewer->Init();
aViewer->SetDefaultLights();
aViewer->SetLightOn();

Aspect_Handle aWindowHandle = (Aspect_Handle) this->winId();

Handle (WNT_Window) aWindow = new WNT_Window(aWindowHandle,Quantity_NOC_MATRAGRAY);

// setup the window for a new view

Handle(V3d_View) aView = aViewer->CreateView();
aView->SetWindow (aWindow);

if (!aWindow->IsMapped())
{
aWindow->Map();
}

myAISContext =new AIS_InteractiveContext(aViewer);

Handle(V3d_Viewer) myViewer = aViewer;
Handle(AIS_InteractiveContext) aContext;
aContext = new AIS_InteractiveContext(myViewer);

BRepPrimAPI_MakeSphere S(gp_Pnt(0,300,0), 100.);
Handle(AIS_Shape) aisthing=new AIS_Shape(S.Shape());
aContext->SetDisplayMode(aisthing,AIS_Shaded);
aContext->Display(aisthing);
aContext->DisplayAll();
aView->MustBeResized();
aView->Redraw();

I'm using Qt5 and a MainWindow with a QMDIArea and try to use a QWidget as a document view.

Thorsten H's picture

Oh, sorry. I didn't know, that Graphic3d_GraphicDevice doesn't exist anymore in OCC6.6.0. Perhaps the "Visualization Users Guide" contains useful information about the new procedure to create a view ("4.2.2 Create a 3D viewer (a Windows example)".

// **************************************************************************
Handle(Aspect_DisplayConnection) aDisplayConnection;
Handle(Graphic3d_GraphicDriver) aGraphicDriver =
Graphic3d::InitGraphicDriver (aDisplayConnection);
TCollection_ExtendedString aName("3DV");
myViewer = new V3d_Viewer (aGraphicDriver,aName.ToExtString (), "");
myViewer -> SetDefaultLights ();
myViewer -> SetLightOn ();

...

Handle (WNT_Window) aWNTWindow;
aWNTWindow = new WNT_Window (GetSafeHwnd());
myView = myViewer -> CreateView();
myView -> SetWindow (a WNTWindow);

// **************************************************************************

marcelo.fontes's picture

Yes .. I saw it and it is exactly what I'm using. But, I'm not using MFC ... so GetSafeHwnd() is not working for me too. I saw some examples using WinId() instead, but it is not working too ... there is no presentantion in the forms.
If I create a window manually using WNT_WIndow package and without embeed it into Qt5 forms, then I can get a visualization, but when I try to embeed it, then does not appear anything.
thank you for your time in responding this.

Thorsten H's picture

I am using Qt5 too. Did you...

1) ...set the following Attributes:
// Avoid Qt background clears to improve resizing speed,
// along with a couple of other attributes
setAttribute( Qt::WA_NoSystemBackground, false);
//setAttribute( Qt::WA_WState_Visible, false );

// Clear buffer before start painting?:
setAttribute( Qt::WA_OpaquePaintEvent );

// Turn off double buffering:
setAttribute( Qt::WA_PaintOnScreen, true );
...
hWnd->SetFlags( WDF_NOERASEBKGRND );

2) Override paintEngine() to return NULL if the view is active (I can turn of my QOCViewer):

QPaintEngine * QOCViewer::paintEngine() const
{
if (getActive()) return NULL;
return QWidget::paintEngine();
}

marcelo.fontes's picture

Hello Thorsten, thank you again.
I tried your code, but I got few errors with hWnd variable and getActive() function. For both the compiler cannot identify them.
After removing hWnd from code and replace getAcive() by getActiveWindow() it compiles but shows only a black background with no drawing.
I'm thinking in give a step back and remove Qt5 and OCC6.6 and use Qt4 and OCC6.5.5. They seems to be a QtOCC viewer that works fine and I do not need to spend time with this kind of things. I jus need a simple viewer to start doing my tool.

which version of OCC and Qt do you suggest??? If this does not work too, I'll try to use OpenInventor ...

Forum supervisor's picture

Dear Marcello,
We would suggested you to take Qt 4 with OCCT 6.6.0 which are known to work together (see Qt samples).
Best regards

ffff's picture

I am programming in qt 4.8.4 and opencascade 6.5.5, I have a similar problem, I can't fix it. When I build my project in debug mode I don't have any problems but I have it in release mode.

This is the piece of code where I catch the failure:

static Handle(Graphic3d_WNTGraphicDevice) defaultdevice;

try {
if( defaultdevice.IsNull() )
defaultdevice = new Graphic3d_WNTGraphicDevice("TKOpenGl");
}
catch(Standard_Failure ) {

QMessageBox::critical(0, tr("About occt"),
tr("Fatal error in graphic initialisation!"),
QMessageBox::Apply);
}

How can I fix it? updating with occt 6.6.0 or can I fix it in another way?

Regards

Thorsten H's picture

Today I switched my code to OCE-0.13 (https://github.com/tpaviot/oce/tree/OCE-0.13) wich based on OpenCASCADE 6.6.0.

Now I am using OCE 0.13 and Qt 5.0.2. I always try to stay updated, but I don't get Qt 5.1 compiled.
You should create a new class "QOCViewer" which derives from QWidget.

Implement a static function to create the V3d_Viewer:
---snip---
static Handle(V3d_Viewer) QOCViewer::createV3D_Viewer(
const Standard_CString aDisplay,
const Standard_ExtString aName,
const Standard_CString aDomain,
const Standard_Real ViewSize,
const V3d_TypeOfOrientation ViewProj,
const Standard_Boolean ComputedMode,
const Standard_Boolean aDefaultComputedMode )
{
Handle(Graphic3d_GraphicDriver) aGraphicDriver = new OpenGl_GraphicDriver ("TKOpenGl");
aGraphicDriver->Begin (new Aspect_DisplayConnection());
TCollection_ExtendedString aNameOfViewer ("Visu3D");
Handle(V3d_Viewer) aViewer = new V3d_Viewer(
aGraphicDriver, aName, aDomain, ViewSize, ViewProj,
Quantity_NOC_GRAY30, V3d_ZBUFFER, V3d_GOURAUD, V3d_WAIT,
ComputedMode, aDefaultComputedMode, V3d_TEX_NONE);
return aViewer;
}
---snap---

Somewhere in your class create viewer, view and context:
---snip---
// Create viewer
TCollection_ExtendedString a3DName("Visu3D");
QString display = "";
m_V3DViewer = QOCViewer::createV3D_Viewer(
display.toLatin1().data(),
a3DName.ToExtString(),
"", 3000.0,
V3d_XposYnegZpos,
Standard_True, Standard_True );
//
m_V3DViewer->SetDefaultTypeOfView(V3d_ORTHOGRAPHIC);
m_V3DViewer->SetDefaultLights();
m_V3DViewer->SetLightOn();

// Create view
m_V3DView = m_V3DViewer->CreateView();
m_V3DView->SetBackgroundColor(Quantity_NOC_BLACK);

// Create context
m_Context = new AIS_InteractiveContext(m_V3DViewer);

// Do some window stuff
// Avoid Qt background clears to improve resizing speed,
// along with a couple of other attributes
setAttribute( Qt::WA_NoSystemBackground, false);

// Clear buffer before start painting?:
setAttribute( Qt::WA_OpaquePaintEvent );

// Turn off double buffering:
setAttribute( Qt::WA_PaintOnScreen, true );

// Map view QOCViewer window handle
Aspect_Handle windowHandle = (Aspect_Handle)winId();
Handle(WNT_Window) hWnd = new WNT_Window(windowHandle);
hWnd->SetFlags( WDF_NOERASEBKGRND );
m_V3DView->SetWindow( hWnd );
if ( !hWnd->IsMapped() ){
hWnd->Map();
}
---snap---

To eliminate flickering make "paintEngine()" return NULL:
---snip---
QPaintEngine* QOCViewer::paintEngine() const
{
if (!m_V3dView.IsNull()) return NULL;
return QWidget::paintEngine();
}
---snap---

Hope this helps.

Regards
Thorsten

Dmitry Kidyaev's picture

May be you should look the folowing topic.
http://www.opencascade.org/org/forum/thread_25373/?forum=3

That was critically important for my implementation of the QWidget OCC dervied class.
I mean that it was the main difference between View.cxx class in OCC samples and the reality of using Qt 5.1.1.

Daniel Park's picture
Shing Liu's picture

Hope my blog could help you.
I will update it with OpenCascade6.7.0.

ffff's picture

I am programming in qt 4.8.4 and opencascade 6.5.5, I have a similar problem, I can't fix it. When I build my project in debug mode I don't have any problems but I have it in release mode.

This is the piece of code where I catch the failure:

static Handle(Graphic3d_WNTGraphicDevice) defaultdevice;

try {
if( defaultdevice.IsNull() )
defaultdevice = new Graphic3d_WNTGraphicDevice("TKOpenGl");
}
catch(Standard_Failure ) {

QMessageBox::critical(0, tr("About occt"),
tr("Fatal error in graphic initialisation!"),
QMessageBox::Apply);
}

How can I fix it? updating with occt 6.6.0 or can I fix it in another way?

Regards

Daniel

Daniel Park's picture

Hello Daniel
I would upgrade to qt 5.1 occ 6.7