PDA

View Full Version : create a new widget dynamically



rimie23
20th May 2012, 11:06
Hi,
i want to create new widget dynamically
i will explain to you what i have
i have two class
1-maonwindow contain function to create dockwidget,button,
2-ogrewidget contain function like paint,createscene....
i make like that

ogreWidget = new OgreWidget(this);
setCentralWidget(ogreWidget);

i add now a new function to the class ogrewidget that "add_camera" i want when i add camera i add a new widget but in this new widget there is the same dockwidget in the mainwindows (if i add 8 cam , i must see 8 widget)

i tried to use just signal slot and i make like that
in the function add_cam i add signal addcamsignal();


void OgreWidget::add_cam(double offsetX ,double offsetY)
{
//code to add a new cam
emit addcamsignal();
}


and in the mainwidows i make like that


MainWindow::MainWindow()
{
this->setBaseSize(1500,1500);
ogreWidget = new OgreWidget(this);
//ogreWidget->setBaseSize(1000,1000);
setCentralWidget(ogreWidget);
createModel();
// createActionMenus();
createDockWidget();
connect(ogreWidget, SIGNAL(add_camSignal()), this, SLOT(createwidget()));
}
void MainWindow::createwidget()
{
QWidget *camwidget = new QWidget(this);


}



but when i run and when i add new cam i do not see new widget
is there method to make that?

Talei
20th May 2012, 16:02
Well yes there is and it's called show() or exec() method for the QWidgete subclass.

In your code what You do is create on the heap QWidget and that's all, You need to make it visible (to appear on the screen).
I also recommend RTM.

rimie23
20th May 2012, 17:09
can you more explain i do not understand what you want to say

wysota
20th May 2012, 17:11
Talei wants to say that if you want a widget to become visible, you need to call show() on it.

rimie23
20th May 2012, 17:28
yes i make like that too


void MainWindow::createwidget()
{
QWidget *camwidget = new QWidget(this);
camwidget->show();

}

i still can not see it

i sored too zll the widget created in vector


void MainWindow::createwidget()
{
QWidget *camwidget = new QWidget();
listwidget.push_back(camwidget);

for(int i=0;i<listwidget.size();i++)
{
listwidget[i]->show();

}

}

the same result
i can't see the widget

d_stranz
20th May 2012, 19:11
QWidget doesn't really have a visual appearance - it's just a blank window with nothing in it. You are creating it with zero size, with a default position of (0,0) relative to your MainWindow. Not only that, but you are creating it and then losing the pointer as soon as your createwidget method goes out of scope, so how will you get to the camwidget once the createwidget method exits?

Some questions:

How do you know that the "createwidget" slot is actually called? Did you set a breakpoint with your debugger and see that it stops there?

(I'll bet you didn't - since you have used "add_camSignal" in the connect() call in MainWindow, but your OgreWidget is emitting a signal called "addcamsignal", there is no way for createwidget() to ever be called by the code you have shown).

rimie23
20th May 2012, 20:47
(I'll bet you didn't - since you have used "add_camSignal" in the connect() call in MainWindow, but your OgreWidget is emitting a signal called "addcamsignal", there is no way for createwidget() to ever be called by the code you have shown).
thanks it's mistake i fixed it , it add to me now the new widget :)

QWidget doesn't really have a visual appearance - it's just a blank window with nothing in it. You are creating it with zero size, with a default position of (0,0) relative to your MainWindow. Not only that, but you are creating it and then losing the pointer as soon as your createwidget method goes out of scope, so how will you get to the camwidget once the createwidget method exits?
yes i make like that to see my widget

QWidget *camwidget = new QWidget();
camwidget->setGeometry(QRect(0, 0, 98, 28));
listwidget.push_back(camwidget);
for(int i=0;i<listwidget.size();i++)
{
listwidget[i]->show();
}
}

But is it better to create tabwidget and when i create a new widget it will be a new widget in the tab?
if yes have you an idea how i do that ?

another thing

when i create a new widget it is empty
i want to make the same (dockwidget exist in the main window make it in this new widgets

Talei
20th May 2012, 23:19
That's depends entirely on You. If you want to create Tab'ed like UI then yes You can.


But is it better to create tabwidget and when i create a new widget it will be a new widget in the tab?
if yes have you an idea how i do that ?

Do like this ("easy" approach using QDesigner/QtCreator - You can do that from code ass well):
1. in the designer place tabwidget
2. in code, when You create New QWidget() create another tab, and place into that newly created QWidget.


when i create a new widget it is empty
i want to make the same (dockwidget exist in the main window make it in this new widgets

If you create tabWidget then there is no need for DockWidgets. If you want to create each viewport as separate window then You will need to store it somewhere in the same meaner as QWidget list i.e. as a list.

Pseudo code, something like this (this for creating tab, add camera widget):

QWidget *camWidget = new QWidget();
listWidget.append(camWidget);
ui->tabWidget->addTab(listWidget.at(i));

Here is how I would do that (not necessary "right way of doing this"):

1. create "base" widget with layout, dockwidget, viewport (is it ogre widget?), lets call it OgreWidget <- this is a "wraper" for gui widgets, not actual "ogre/viewport" widget
2. create new OgreWidget each time You need new viewport (because OgreWidget has everything You need, i.e. dockwidget, layout, actual viewport You don't need to worry about this, as long as each widget has parent)
3. add newly created OgreWidget to QList<OgreWidget*>

And Now, because OgreWidget is QWidget subclass You can:
1. show() it as INDEPENDENT window
2. place it inside i.e. TabWidget

rimie23
21st May 2012, 08:20
Thanks for repling ,



1. create "base" widget with layout, dockwidget, viewport (is it ogre widget?), lets call it OgreWidget <- this is a "wraper" for gui widgets, not actual "ogre/viewport" widget
2. create new OgreWidget each time You need new viewport (because OgreWidget has everything You need, i.e. dockwidget, layout, actual viewport You don't need to worry about this, as long as each widget has parent)
3. add newly created OgreWidget to QList<OgreWidget*>

it's very good idea ,
But to render my scene in ogreWidget (in the mainwidow) i use camera , and i want in this new widget i use to render my scene the new camera (i create new widget when i add new camera )that mean the only deference beteween the mainwindow, and the other new widget is thet each widget use new camera

can i use your idea in this case ?(because it's very good idea) and when i create the new ogrewidget i send signal (the name and the position of the camera) to the classs ogrewidget?

rimie23
21st May 2012, 12:54
i write like that


void MainWindow::createwidget()
{
QWidget *camwidget = new OgreWidget();
//camwidget->setGeometry(QRect(0, 0, 98, 28));
listwidget.push_back(camwidget);

for(int i=0;i<listwidget.size();i++)
{
listwidget[i]->show();

}

}

it make to me assertion exception

R6010 abort has been called



because in the class ogrewidget there is a function that initialize the sustem and it must call one time in the project

rimie23
21st May 2012, 19:39
Hi again
is there another idea ?

Talei
21st May 2012, 19:45
The R6010 AFAIK is allegro internal problem and is called on crash / something wrong was happen.

Basically idea with multiple view-ports uses same data across all views. Each time You need new camera do something like this:

initialize view-port (ogl or whatever You are using)
"populate view-port" with SAME data from primary view
in new view change camera position
show new widget

rimie23
21st May 2012, 20:34
Basically idea with multiple view-ports uses same data across all views.
viewport is the same idea of widget?
because i know in ogre the number of viewport it must be static

initialize view-port (ogl or whatever You are using)
"populate view-port" with SAME data from primary view
in new view change camera position
show new widget
can you please more explain this idea?

Talei
21st May 2012, 22:35
AFAIK You have 3 solution to this problem, and each gave different possibilities.
Note. I never used Ogre so I can't answer Ogre specific question but ideas below should work.

I. "Off-screen" rendering
1. Create only ONE ogl context (You are using Ogre for that, so create only one oger class)
2. Paint not to screen directly, but to i.e. QPixmap.
3. Create list of QWidgets with qdockwidget and another QWidget (lets call it view)
4. In that "view" simply paint QPixmap that was drawn by Ogre widget.

In that case You have only one ogl context and using off-screen drawing You visualise Your world.

II. Posted by me in previous reply.
1. Create template QWidget with qdock widget and Actual Ogre widget. That is your main viewport class, and also WILL be used as Main window.
1a. In "Template" QWidget do Ogre initialization i.e. in event onShow() or simply in constructor on the QWidget subclass.
2. Initialize FIRST widget, place it in MainWindow (or whatever name Your basic class name is), this is Your main Ogre widget and append it to the list at first position i.e. QList<YourQWidgetSubclassWithOgre*> widgetList;.
2a. Build VBO/DisplayList for Your 3D mesh data, create shaders etc...
3. When "new camera" is requested create that widget on the heap and add it to the list i.e. QList<YourQWidgetSubclassWithOgre*> widgetList;.
3a. Pass, from the FIRST WIDGET - from step 2a., to that subclass, pointers to the 3D data, meshes, shaders and paint them in that new camera view.
Note. Now all data is in the GPU memory so there is no need to send again same data so simply reuse the data.
4. Show New Camera widget.
5. Change Camera position in that new Camera View.

Note. I mentioned this approach because You wanted to have INDEPENDENT windows that You can move around screen etc.

III. Use OpenGL build in view-port support (this is easiest and probably what You want)
This will DIVIDE Your main OgreWidget into smaller areas, where You can show scene from different cameras.
Minus is that You can't move independently those smaller areas around screen, they are part of main widget.
For this use glViewport (google it).

rimie23
23rd May 2012, 15:46
Hi , again

it's true that this idea is what i want

III. Use OpenGL build in view-port support (this is easiest and probably what You want)
This will DIVIDE Your main OgreWidget into smaller areas, where You can show scene from different cameras.
Minus is that You can't move independently those smaller areas around screen, they are part of main widget.
(google it).
But bbecause the viewport is a part from main widget ,and i can't add dynamically the viewport i can't use it

i think to use this idea it's the most appropriate idea


II. Posted by me in previous reply.
1. Create template QWidget with qdock widget and Actual Ogre widget. That is your main viewport class, and also WILL be used as Main window.
1a. In "Template" QWidget do Ogre initialization i.e. in event onShow() or simply in constructor on the QWidget subclass.
2. Initialize FIRST widget, place it in MainWindow (or whatever name Your basic class name is), this is Your main Ogre widget and append it to the list at first position i.e. QList<YourQWidgetSubclassWithOgre*> widgetList;.
2a. Build VBO/DisplayList for Your 3D mesh data, create shaders etc...
3. When "new camera" is requested create that widget on the heap and add it to the list i.e. QList<YourQWidgetSubclassWithOgre*> widgetList;.
3a. Pass, from the FIRST WIDGET - from step 2a., to that subclass, pointers to the 3D data, meshes, shaders and paint them in that new camera view.
Note. Now all data is in the GPU memory so there is no need to send again same data so simply reuse the data.
4. Show New Camera widget.
5. Change Camera position in that new Camera View.

But i have some questions

1. Create template QWidget with qdock widget and Actual Ogre widget. That is your main viewport class, and also WILL be used as Main window.
1a. In "Template" QWidget do Ogre initialization i.e. in event onShow() or simply in constructor on the QWidget subclass.
like how i do in my project the first time ?


MainWindow::MainWindow()
{
ogreWidget = new OgreWidget(this);
setCentralWidget(ogreWidget);
createActionMenus();
createDockWidget();
}

and for my ogre insialization it is in the ogrewidget initalisation
ogrewidget in viewport


void OgreWidget::createViewports(void)
{
// Create one viewport, entire window
Ogre::Viewport* vp = mWindow->addViewport(mCamera);
vp->setBackgroundColour(Ogre::ColourValue(0,0,0));

// Alter the camera aspect ratio to match the viewport
mCamera->setAspectRatio(
Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));
}


Note: when i create new camera and new widget i change mcamera by te new camera but mwindow is i change it by my new widget? OR I ADD IN THE INITIALIZATION OF OGREWIDGET PARAMETER THE NAME OF THE WIDGET(OGREwIDGET OR THE NEW WIDGETS ) WITH THAT HE WILL CREATE TO ME MANY MAINWINDOW??
with this code i can see in my window what the camera see.


2. Initialize FIRST widget, place it in MainWindow (or whatever name Your basic class name is), this is Your main Ogre widget and append it to the list at first position i.e. QList<YourQWidgetSubclassWithOgre*> widgetList;.
the first widget is
ogreWidget in my case ?

MainWindow::MainWindow()
{
ogreWidget = new OgreWidget(this);
setCentralWidget(ogreWidget);


2a. Build VBO/DisplayList for Your 3D mesh data, create shaders etc...
you mean i create my scene and show it ?or whatb you mean by " Build VBO/DisplayList"

3a. Pass, from the FIRST WIDGET - from step 2a., to that subclass, pointers to the 3D data, meshes, shaders and paint them in that new camera view.
Note. Now all data is in the GPU memory so there is no need to send again same data so simply reuse the data.
what you mean her?i did not understand this step

i ma sorry because i ask many question but i can't found idea or exemple similat as what i want to do

Talei
23rd May 2012, 21:17
like how i do in my project the first time ?
yes


and for my ogre insialization it is in the ogrewidget initalisation
ogrewidget in viewport
yes

Keep in mind that with this approach You are dealing with the LIST. So first ogreWidget is widget that is first in the widget list. i.e. QList<ogreWidget*> listWidgets; listWidgets.first() <- this one is first.

I see that You don't know difference between immediate mode and VBO/DisplayList so You can skip past 2a.
Basically what I meant was:
Create VBO (Vertex Buffer object) with Your geometry data. After that You will have pointer to the data and geometry will be kept in GPU memory. Then, instead of drawing (== sending data to the GPU each time) N times same data (N == viewport widget) You simply draw from the GPU memory, with is much faster. Only difference is that camera position differ for each viewport.

rimie23
23rd May 2012, 22:13
You simply draw from the GPU memory, with is much faster. Only difference is that camera position differ for each viewport.
the name and the position of the camera differ
i will try to applicate this idea (i do not know why it seem to me bizarre)


Create VBO (Vertex Buffer object) with Your geometry data.
where i create that ? in my classe ogrewidget or my class mainwindow(ogrewidget contain all function like paint,resize... but mainwindows it is for the interface?

Talei
23rd May 2012, 22:59
Camera:
I would keep only one camera, so in each viewport class I would keep current viewport camera position. In repaint function, for each viewport, simply move camera around, no need for multiple cameras.

VBO:
I don't know, maybe Ogre by default uses VBO (I saw on Ogre wiki that there is some sort of asset manager but didn't find any info regarding internal VBO usage, search Ogre wiki/forum) so then there is no problem, as I said before I didn't use Ogre. But this is just for performance and if you scene is simple then there won't be any performance impact (but this is not the "right" way to do this because currently immediate mode is treated as depreciate).

rimie23
24th May 2012, 14:29
No, i can't i must use many camera
because the aim of my project is to use many camera and render what see each frame


i think i must change all the idea

because i see this software "vicon" it similar as what i want
http://blog.digitalcontentproducer.com/briefingroom/wp-content/uploads/2009/04/bladeprocess1.jpg

now when i run my project my scene is rendred in all the window(central window)

to make it like the photi i have two idea and their problem if you can advice to me what is the appropriate idea
1- the first idea i can devise y window with ogre like the photo BUT when i separate i can't make the lines that mean i cant defrent betewwen the veiw AND i can't write the name of the viewport is there methode in qt to draw lines like that(like the picture)(line in blue and lines in white , the lines that represent the edge of each viewport ?

2-i less the central widget as it , and i add otheres scorelarea to render the scene with the camera in it , BUT her the problem is how i said in my program to render the scen inside the scroller area