tonnot
29th November 2011, 19:29
Hello and excuse for my todays posts
Finally I cannot do a correct solution for a common problem. Need your help.
I want to have a QGrapchics framework view & edit capabilities for manage big vectorial worlds. I'm testing my program against a world with 100000 item entities.
Ok. The feed of system is fast and also its initial visualization.
The problem was when I want to take control over the paint event. (in example to know when the draw is done)
If I use a paintevent, I have to recall QgraphicsView::paint(). No problem.
The big problem I have is when I want to create a dynamic new element (havin the other 100000 items). In example , a new line. To create this line I do the first click and then, when moving the mouse, as expected, I want to view the line. No problem with this. The problem is that I have a repaint for every item intercepted. In case of drawing a new rectangle the problem grows.
To avoid this, I have tried this trick.
I create a temporal item, not added to the scene. On mouse_move_event I throws an invalidate event for the foreground layer, in which I'm going to draw this temporal item. I expected that exist some 'auto' buffer strategy at itemslayer, but not. I see how I have a paintevent. Ok, to avoid this, I create a pixmap at the begin of my edit process, copying the screen , later at the paintevent, where I know if I'm editing, I make a pixmap copy to later draw the temporal line at drawforeground event. (subclased). I have passing a rect for the whole scene ( I pass full scene rect because if no by any reason, foreground painting is strange) (I know that a right rect, restricted only to the area needed, would be better, but...)
The big problem: I have to 'recall' Graphicsview::paint, because if not the drawforeground is not throwed. But doing this means that the QGraphicscene order a repaint for the items...
This is the code for the paintevent of my class, that extends QGrapchisView.
void A_Gview2D::paintEvent(QPaintEvent *event) {
if (w_temp_item!=0 )
{
QPainter painter(this->viewport());
painter.drawPixmap(0,0,*pixMap_cached1);
QGraphicsView::paintEvent(event);
// This is the big problem
// If I dont use it, I have not drawforeground , If I use it I have drawforeground but before repaint
// all items....
}
else
{
w_qtutil->time_start();
QGraphicsView::paintEvent(event);
w_qtutil->time_stop();
qDebug()<< w_qtutil->time_spent()<<"";
}
}
Mousemove code for a rectangle example:
if (w_click_count==1)
{
w_current_Gitem = new A_GItem(WW::Graph_rectangle, QRect(0,0,0,0), punteroo,0);
w_current_Gitem->w_set_draw_props(1,1,1);
w_current_Gitem->setPos(x,y);
last_point_x=x;last_point_y=y;
w_click_count++;
G_view->w_set_temp_item(w_current_Gitem); // set the temporal item
G_view->w_pixmap_copy(); // copy screen
return;
}
else
{
double center_x=(last_point_x+x) /2;
double center_y=(last_point_y+y) /2;
double ix=W_MATH::my_abs(x-last_point_x)/2;
double iy=W_MATH::my_abs(y-last_point_y)/2;
w_current_Gitem->w_set_rect( QRectF(-ix,-iy,ix*2,iy*2));
w_current_Gitem->setPos(center_x,center_y);
if (w_mouse_action==5) //click
{
w_click_count=0; // done.
G_scene->addItem(w_current_Gitem);
G_view->w_set_temp_item(0);
}
else
{ w_click_count++;
G_scene->invalidate(QRectF(x1,y1,xx,yy), QGraphicsScene::ForegroundLayer);
// x1,y1,xx,yy are the total scene limits.
return;
}
}
I need your help. Thanks
Finally I cannot do a correct solution for a common problem. Need your help.
I want to have a QGrapchics framework view & edit capabilities for manage big vectorial worlds. I'm testing my program against a world with 100000 item entities.
Ok. The feed of system is fast and also its initial visualization.
The problem was when I want to take control over the paint event. (in example to know when the draw is done)
If I use a paintevent, I have to recall QgraphicsView::paint(). No problem.
The big problem I have is when I want to create a dynamic new element (havin the other 100000 items). In example , a new line. To create this line I do the first click and then, when moving the mouse, as expected, I want to view the line. No problem with this. The problem is that I have a repaint for every item intercepted. In case of drawing a new rectangle the problem grows.
To avoid this, I have tried this trick.
I create a temporal item, not added to the scene. On mouse_move_event I throws an invalidate event for the foreground layer, in which I'm going to draw this temporal item. I expected that exist some 'auto' buffer strategy at itemslayer, but not. I see how I have a paintevent. Ok, to avoid this, I create a pixmap at the begin of my edit process, copying the screen , later at the paintevent, where I know if I'm editing, I make a pixmap copy to later draw the temporal line at drawforeground event. (subclased). I have passing a rect for the whole scene ( I pass full scene rect because if no by any reason, foreground painting is strange) (I know that a right rect, restricted only to the area needed, would be better, but...)
The big problem: I have to 'recall' Graphicsview::paint, because if not the drawforeground is not throwed. But doing this means that the QGraphicscene order a repaint for the items...
This is the code for the paintevent of my class, that extends QGrapchisView.
void A_Gview2D::paintEvent(QPaintEvent *event) {
if (w_temp_item!=0 )
{
QPainter painter(this->viewport());
painter.drawPixmap(0,0,*pixMap_cached1);
QGraphicsView::paintEvent(event);
// This is the big problem
// If I dont use it, I have not drawforeground , If I use it I have drawforeground but before repaint
// all items....
}
else
{
w_qtutil->time_start();
QGraphicsView::paintEvent(event);
w_qtutil->time_stop();
qDebug()<< w_qtutil->time_spent()<<"";
}
}
Mousemove code for a rectangle example:
if (w_click_count==1)
{
w_current_Gitem = new A_GItem(WW::Graph_rectangle, QRect(0,0,0,0), punteroo,0);
w_current_Gitem->w_set_draw_props(1,1,1);
w_current_Gitem->setPos(x,y);
last_point_x=x;last_point_y=y;
w_click_count++;
G_view->w_set_temp_item(w_current_Gitem); // set the temporal item
G_view->w_pixmap_copy(); // copy screen
return;
}
else
{
double center_x=(last_point_x+x) /2;
double center_y=(last_point_y+y) /2;
double ix=W_MATH::my_abs(x-last_point_x)/2;
double iy=W_MATH::my_abs(y-last_point_y)/2;
w_current_Gitem->w_set_rect( QRectF(-ix,-iy,ix*2,iy*2));
w_current_Gitem->setPos(center_x,center_y);
if (w_mouse_action==5) //click
{
w_click_count=0; // done.
G_scene->addItem(w_current_Gitem);
G_view->w_set_temp_item(0);
}
else
{ w_click_count++;
G_scene->invalidate(QRectF(x1,y1,xx,yy), QGraphicsScene::ForegroundLayer);
// x1,y1,xx,yy are the total scene limits.
return;
}
}
I need your help. Thanks