Rendering single layer from mapcanvas

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Rendering single layer from mapcanvas

bonar
Hi guys, Tim & Dr.Marco

I was tried to display real-time data in my mapcanvas. In my mapcanvas, i have 4 layer, but i juz want to refresh 1 layer only(this layer retrieve data from PostGis) from the mapcanvas without refreshing all layer in the mapcanvas. I already searching from this forum and Google it, and the result is i should use QgsMapCanvasItem that have that capabilities to rendering single layer without refreshing mapcanvas. But, i don't know how to implement it in my application. I'm using sample application from Mr.Tim Sutton, it is a great tutorial for a beginner like me, and i think its better to include the code in here. This is what i already done:


//Setting my layer

mpMapCanvas= new QgsMapCanvas(0, 0);
  mpMapCanvas->enableAntiAliasing(true);
  mpMapCanvas->useImageToRender(true);
  mpMapCanvas->setCanvasColor(QColor(255, 255, 255));
  mpMapCanvas->freeze(false);
  mpMapCanvas->setVisible(true);

  QString myLayerPathNegeri         = LAYERPATH() + "klkv_state.shp";
  QString myLayerBaseNameNegeri     = "klkv_state";
  QString myProviderName            = "ogr";

  QString myLayerPathDistrict         = LAYERPATH() + "klkv_district.shp";
  QString myLayerBaseNameDistrict     = "klkv_district";

  QString myLayerPathMukim         = LAYERPATH() + "klkv_mukim.shp";
  QString myLayerBaseNameMukim     = "klkv_mukim";

QString myLayerPathPoi         = "location_poi";
  QString myLayerBaseNamePoi     = "location_poi";

QgsVectorLayer * mypLayerNegeri = new QgsVectorLayer(myLayerPathNegeri, myLayerBaseNameNegeri, myProviderName);

  QgsVectorLayer * mypLayerDistrict = new QgsVectorLayer(myLayerPathDistrict, myLayerBaseNameDistrict, myProviderName);

  QgsVectorLayer * mypLayerMukim = new QgsVectorLayer(myLayerPathMukim, myLayerBaseNameMukim, myProviderName);

  QgsVectorLayer * mypLayerPoi = new QgsVectorLayer(POSTGIS_LAYER_SETUP_INCIDENT_POI_FUNC(), myLayerBaseNamePoi, "postgres");


QgsSingleSymbolRenderer *mypRendererNegeri = new QgsSingleSymbolRenderer(mypLayerNegeri->geometryType());
  QList<QgsMapCanvasLayer> myLayerSet;
  mypLayerNegeri->setRenderer(mypRendererNegeri);

  QgsSingleSymbolRenderer *mypRendererDistrict = new QgsSingleSymbolRenderer(mypLayerDistrict->geometryType());
  mypLayerDistrict->setRenderer(mypRendererDistrict);

  QgsSingleSymbolRenderer *mypRendererMukim = new QgsSingleSymbolRenderer(mypLayerMukim->geometryType());
  mypLayerMukim->setRenderer(mypRendererMukim);


QgsSingleSymbolRenderer *mypRendererPoi = new QgsSingleSymbolRenderer(mypLayerPoi->geometryType());
  mypLayerPoi->setRenderer(mypRendererPoi);


QgsMapLayerRegistry::instance()->addMapLayer(mypLayerNegeri, TRUE);
  QgsMapLayerRegistry::instance()->addMapLayer(mypLayerDistrict, TRUE);
  QgsMapLayerRegistry::instance()->addMapLayer(mypLayerMukim, TRUE);
QgsMapLayerRegistry::instance()->addMapLayer(mypLayerPoi, TRUE);

myLayerSet.append(QgsMapCanvasLayer(mypLayerPoi));
myLayerSet.append(QgsMapCanvasLayer(mypLayerMukim));
  myLayerSet.append(QgsMapCanvasLayer(mypLayerDistrict));
  myLayerSet.append(QgsMapCanvasLayer(mypLayerNegeri));

mpMapCanvas->setLayerSet(myLayerSet);


//I make a Qtimer to check if any update position for mypLayerPoi from updatingLocationPoiLayer() function

QTimer *timerPoiRenderer = new QTimer(this);
  connect(timerPoiRenderer, SIGNAL(timeout()), this, SLOT(updatingLocationPoiLayer()));
  timerPoiRenderer->start(10 * 1000);// 10 seconds


//this is how i tried to using QgsMapCanvasItem, sorry for the code because i am beginner for this QGis, so i juz try to play-around with the QgsMapCanvasItem code .

void MyMain::updatingLocationPoiLayer()
{

  QGraphicsScene *mScene = new QGraphicsScene();
  QgsMapCanvasMap* mMap = new QgsMapCanvasMap(mpMapCanvas);
  mScene->addItem( mMap );
  mScene->update();
  QList<QGraphicsItem*> list = mScene->items();
  QList<QGraphicsItem*>::iterator it = list.begin();

  while ( it != list.end() ){
          QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem*>( *it );

          if(item){
                  item->updatePosition();
                  QMessageBox::information( this, tr( "TEST" ), tr( "Update rendering" ) );
          }else{
//it will goes here.
                  QMessageBox::information( this, tr( "TEST" ), tr( "NOT Update rendering" ) );
          }

          it++;
  }
}

from my reading,what i understand is i should use QgsMapCanvasItem::updatePosition() to make my mapcanvas look like real-time. Is it true? And i really hope you guys can teach me about how to implement it in my code.


Thanks in advance,
Bonar
Reply | Threaded
Open this post in threaded view
|

AW: Rendering single layer from mapcanvas

Hugentobler  Marco
Hi Bonar

QGIS renders the map into one image canvas item (QgsMapCanvasMap). Currently, it is not possible to refresh only one layer in this item.
However, it is possible to render the content of the three layers that stay constant into a QgsMapCanvasMap (as you do now with all the four layers). For the layer that changes you could create a new canvas item (as a new subclass of QgsMapCanvasItem). In this subclass you need to create a QgsVectorLayer configured with your database instance . Then you could implement the paint method, there query all the features inside the view extent, use the transformation methods of QgsMapCanvasItem  (toCanvasCoordinates()) and finally use QPainter to draw the objects as you want. Important is that the new item has the same size as the mapcanvas and also a transparent background such that you may see the content of the other three background layers.

If then something in the datasource changes, you update your item class and only the item with one layer is repainted. The background with the three other layers stays the same.


Regards,
Marco

 


-----Ursprüngliche Nachricht-----
Von: [hidden email] im Auftrag von bonar
Gesendet: Mo 25.05.2009 11:41
An: [hidden email]
Betreff: [Qgis-developer] Rendering single layer from mapcanvas
 

Hi guys, Tim & Dr.Marco

I was tried to display real-time data in my mapcanvas. In my mapcanvas, i
have 4 layer, but i juz want to refresh 1 layer only(this layer retrieve
data from PostGis) from the mapcanvas without refreshing all layer in the
mapcanvas. I already searching from this forum and Google it, and the result
is i should use QgsMapCanvasItem that have that capabilities to rendering
single layer without refreshing mapcanvas. But, i don't know how to
implement it in my application. I'm using sample application from Mr.Tim
Sutton, it is a great tutorial for a beginner like me, and i think its
better to include the code in here. This is what i already done:


//Setting my layer

mpMapCanvas= new QgsMapCanvas(0, 0);
  mpMapCanvas->enableAntiAliasing(true);
  mpMapCanvas->useImageToRender(true);
  mpMapCanvas->setCanvasColor(QColor(255, 255, 255));
  mpMapCanvas->freeze(false);
  mpMapCanvas->setVisible(true);

  QString myLayerPathNegeri         = LAYERPATH() + "klkv_state.shp";
  QString myLayerBaseNameNegeri     = "klkv_state";
  QString myProviderName            = "ogr";

  QString myLayerPathDistrict         = LAYERPATH() + "klkv_district.shp";
  QString myLayerBaseNameDistrict     = "klkv_district";

  QString myLayerPathMukim         = LAYERPATH() + "klkv_mukim.shp";
  QString myLayerBaseNameMukim     = "klkv_mukim";

QString myLayerPathPoi         = "location_poi";
  QString myLayerBaseNamePoi     = "location_poi";

QgsVectorLayer * mypLayerNegeri = new QgsVectorLayer(myLayerPathNegeri,
myLayerBaseNameNegeri, myProviderName);

  QgsVectorLayer * mypLayerDistrict = new
QgsVectorLayer(myLayerPathDistrict, myLayerBaseNameDistrict,
myProviderName);

  QgsVectorLayer * mypLayerMukim = new QgsVectorLayer(myLayerPathMukim,
myLayerBaseNameMukim, myProviderName);

  QgsVectorLayer * mypLayerPoi = new
QgsVectorLayer(POSTGIS_LAYER_SETUP_INCIDENT_POI_FUNC(), myLayerBaseNamePoi,
"postgres");


QgsSingleSymbolRenderer *mypRendererNegeri = new
QgsSingleSymbolRenderer(mypLayerNegeri->geometryType());
  QList<QgsMapCanvasLayer> myLayerSet;
  mypLayerNegeri->setRenderer(mypRendererNegeri);

  QgsSingleSymbolRenderer *mypRendererDistrict = new
QgsSingleSymbolRenderer(mypLayerDistrict->geometryType());
  mypLayerDistrict->setRenderer(mypRendererDistrict);

  QgsSingleSymbolRenderer *mypRendererMukim = new
QgsSingleSymbolRenderer(mypLayerMukim->geometryType());
  mypLayerMukim->setRenderer(mypRendererMukim);


QgsSingleSymbolRenderer *mypRendererPoi = new
QgsSingleSymbolRenderer(mypLayerPoi->geometryType());
  mypLayerPoi->setRenderer(mypRendererPoi);


QgsMapLayerRegistry::instance()->addMapLayer(mypLayerNegeri, TRUE);
  QgsMapLayerRegistry::instance()->addMapLayer(mypLayerDistrict, TRUE);
  QgsMapLayerRegistry::instance()->addMapLayer(mypLayerMukim, TRUE);
QgsMapLayerRegistry::instance()->addMapLayer(mypLayerPoi, TRUE);

myLayerSet.append(QgsMapCanvasLayer(mypLayerPoi));
myLayerSet.append(QgsMapCanvasLayer(mypLayerMukim));
  myLayerSet.append(QgsMapCanvasLayer(mypLayerDistrict));
  myLayerSet.append(QgsMapCanvasLayer(mypLayerNegeri));

mpMapCanvas->setLayerSet(myLayerSet);


//I make a Qtimer to check if any update position for mypLayerPoi from
updatingLocationPoiLayer() function

QTimer *timerPoiRenderer = new QTimer(this);
  connect(timerPoiRenderer, SIGNAL(timeout()), this,
SLOT(updatingLocationPoiLayer()));
  timerPoiRenderer->start(10 * 1000);// 10 seconds


//this is how i tried to using QgsMapCanvasItem, sorry for the code because
i am beginner for this QGis, so i juz try to play-around with the
QgsMapCanvasItem code .

void MyMain::updatingLocationPoiLayer()
{

  QGraphicsScene *mScene = new QGraphicsScene();
  QgsMapCanvasMap* mMap = new QgsMapCanvasMap(mpMapCanvas);
  mScene->addItem( mMap );
  mScene->update();
  QList<QGraphicsItem*> list = mScene->items();
  QList<QGraphicsItem*>::iterator it = list.begin();

  while ( it != list.end() ){
          QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem*>( *it );

          if(item){
                  item->updatePosition();
                  QMessageBox::information( this, tr( "TEST" ), tr( "Update
rendering" ) );
          }else{
//it will goes here.
                  QMessageBox::information( this, tr( "TEST" ), tr( "NOT
Update rendering" ) );
          }

          it++;
  }
}

from my reading,what i understand is i should use
QgsMapCanvasItem::updatePosition() to make my mapcanvas look like real-time.
Is it true? And i really hope you guys can teach me about how to implement
it in my code.


Thanks in advance,
Bonar
--
View this message in context: http://n2.nabble.com/Rendering-single-layer-from-mapcanvas-tp2968794p2968794.html
Sent from the qgis-developer mailing list archive at Nabble.com.

_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer

_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer
Reply | Threaded
Open this post in threaded view
|

Re: AW: Rendering single layer from mapcanvas

bonar
Hi Dr.Marco,

Thanks for your reply, i will try to work around with your suggestions and i will inform the output as soon as possible.

Thanks and regard,
Bonar


Hugentobler Marco wrote
Hi Bonar

QGIS renders the map into one image canvas item (QgsMapCanvasMap). Currently, it is not possible to refresh only one layer in this item.
However, it is possible to render the content of the three layers that stay constant into a QgsMapCanvasMap (as you do now with all the four layers). For the layer that changes you could create a new canvas item (as a new subclass of QgsMapCanvasItem). In this subclass you need to create a QgsVectorLayer configured with your database instance . Then you could implement the paint method, there query all the features inside the view extent, use the transformation methods of QgsMapCanvasItem  (toCanvasCoordinates()) and finally use QPainter to draw the objects as you want. Important is that the new item has the same size as the mapcanvas and also a transparent background such that you may see the content of the other three background layers.

If then something in the datasource changes, you update your item class and only the item with one layer is repainted. The background with the three other layers stays the same.


Regards,
Marco

 


-----Ursprüngliche Nachricht-----
Von: qgis-developer-bounces@lists.osgeo.org im Auftrag von bonar
Gesendet: Mo 25.05.2009 11:41
An: qgis-developer@lists.osgeo.org
Betreff: [Qgis-developer] Rendering single layer from mapcanvas
Reply | Threaded
Open this post in threaded view
|

Re: AW: Rendering single layer from mapcanvas

ashjas
In reply to this post by Hugentobler Marco
Hi Marco,

My requirement is also similar to what this post asks...

There are some doubts about ur method...please see if u can find time to answer these..

would I be able to use all the mapTools like selection,identification etc on the layer that i need to update constantly
by using your method (apart the normal static layers..)??

and can i add this live layer on to the legend and also set its symbology from the layer property dialog box?

and i have a doubt about what u said .."In this subclass you need to create a QgsVectorLayer.." so u mean that this subclass should have a QgsVectorlayer object (or as many as the need may be for live layers) on which i keep adding the live objects...and within this subclass i call the paint method which will draw the objects??
and i guess i have to keep the same reference to the only Qgsmapcanvas object for this subclass aswell as the objects are to be drawn only on the mainCanvas.. and what about maprenderer object??should it be also the same object as for the main layers??
and about implementing the paint method.. in short i would be calling the drawFeature of the QgsVectorLayer Class(for all the features on the layer ) from within the paint function that would be custom implemented.. is it?

Please enlighten me..

Thanks for finding time and helping us.. :)

Best Regards.

Ashish

Hugentobler Marco wrote
Hi Bonar

QGIS renders the map into one image canvas item (QgsMapCanvasMap). Currently, it is not possible to refresh only one layer in this item.
However, it is possible to render the content of the three layers that stay constant into a QgsMapCanvasMap (as you do now with all the four layers). For the layer that changes you could create a new canvas item (as a new subclass of QgsMapCanvasItem). In this subclass you need to create a QgsVectorLayer configured with your database instance . Then you could implement the paint method, there query all the features inside the view extent, use the transformation methods of QgsMapCanvasItem  (toCanvasCoordinates()) and finally use QPainter to draw the objects as you want. Important is that the new item has the same size as the mapcanvas and also a transparent background such that you may see the content of the other three background layers.

If then something in the datasource changes, you update your item class and only the item with one layer is repainted. The background with the three other layers stays the same.


Regards,
Marco

 


-----Ursprüngliche Nachricht-----
Von: qgis-developer-bounces@lists.osgeo.org im Auftrag von bonar
Gesendet: Mo 25.05.2009 11:41
An: qgis-developer@lists.osgeo.org
Betreff: [Qgis-developer] Rendering single layer from mapcanvas
 

Hi guys, Tim & Dr.Marco

I was tried to display real-time data in my mapcanvas. In my mapcanvas, i
have 4 layer, but i juz want to refresh 1 layer only(this layer retrieve
data from PostGis) from the mapcanvas without refreshing all layer in the
mapcanvas. I already searching from this forum and Google it, and the result
is i should use QgsMapCanvasItem that have that capabilities to rendering
single layer without refreshing mapcanvas. But, i don't know how to
implement it in my application. I'm using sample application from Mr.Tim
Sutton, it is a great tutorial for a beginner like me, and i think its
better to include the code in here. This is what i already done:


//Setting my layer

mpMapCanvas= new QgsMapCanvas(0, 0);
  mpMapCanvas->enableAntiAliasing(true);
  mpMapCanvas->useImageToRender(true);
  mpMapCanvas->setCanvasColor(QColor(255, 255, 255));
  mpMapCanvas->freeze(false);
  mpMapCanvas->setVisible(true);

  QString myLayerPathNegeri         = LAYERPATH() + "klkv_state.shp";
  QString myLayerBaseNameNegeri     = "klkv_state";
  QString myProviderName            = "ogr";

  QString myLayerPathDistrict         = LAYERPATH() + "klkv_district.shp";
  QString myLayerBaseNameDistrict     = "klkv_district";

  QString myLayerPathMukim         = LAYERPATH() + "klkv_mukim.shp";
  QString myLayerBaseNameMukim     = "klkv_mukim";

QString myLayerPathPoi         = "location_poi";
  QString myLayerBaseNamePoi     = "location_poi";

QgsVectorLayer * mypLayerNegeri = new QgsVectorLayer(myLayerPathNegeri,
myLayerBaseNameNegeri, myProviderName);

  QgsVectorLayer * mypLayerDistrict = new
QgsVectorLayer(myLayerPathDistrict, myLayerBaseNameDistrict,
myProviderName);

  QgsVectorLayer * mypLayerMukim = new QgsVectorLayer(myLayerPathMukim,
myLayerBaseNameMukim, myProviderName);

  QgsVectorLayer * mypLayerPoi = new
QgsVectorLayer(POSTGIS_LAYER_SETUP_INCIDENT_POI_FUNC(), myLayerBaseNamePoi,
"postgres");


QgsSingleSymbolRenderer *mypRendererNegeri = new
QgsSingleSymbolRenderer(mypLayerNegeri->geometryType());
  QList<QgsMapCanvasLayer> myLayerSet;
  mypLayerNegeri->setRenderer(mypRendererNegeri);

  QgsSingleSymbolRenderer *mypRendererDistrict = new
QgsSingleSymbolRenderer(mypLayerDistrict->geometryType());
  mypLayerDistrict->setRenderer(mypRendererDistrict);

  QgsSingleSymbolRenderer *mypRendererMukim = new
QgsSingleSymbolRenderer(mypLayerMukim->geometryType());
  mypLayerMukim->setRenderer(mypRendererMukim);


QgsSingleSymbolRenderer *mypRendererPoi = new
QgsSingleSymbolRenderer(mypLayerPoi->geometryType());
  mypLayerPoi->setRenderer(mypRendererPoi);


QgsMapLayerRegistry::instance()->addMapLayer(mypLayerNegeri, TRUE);
  QgsMapLayerRegistry::instance()->addMapLayer(mypLayerDistrict, TRUE);
  QgsMapLayerRegistry::instance()->addMapLayer(mypLayerMukim, TRUE);
QgsMapLayerRegistry::instance()->addMapLayer(mypLayerPoi, TRUE);

myLayerSet.append(QgsMapCanvasLayer(mypLayerPoi));
myLayerSet.append(QgsMapCanvasLayer(mypLayerMukim));
  myLayerSet.append(QgsMapCanvasLayer(mypLayerDistrict));
  myLayerSet.append(QgsMapCanvasLayer(mypLayerNegeri));

mpMapCanvas->setLayerSet(myLayerSet);


//I make a Qtimer to check if any update position for mypLayerPoi from
updatingLocationPoiLayer() function

QTimer *timerPoiRenderer = new QTimer(this);
  connect(timerPoiRenderer, SIGNAL(timeout()), this,
SLOT(updatingLocationPoiLayer()));
  timerPoiRenderer->start(10 * 1000);// 10 seconds


//this is how i tried to using QgsMapCanvasItem, sorry for the code because
i am beginner for this QGis, so i juz try to play-around with the
QgsMapCanvasItem code .

void MyMain::updatingLocationPoiLayer()
{

  QGraphicsScene *mScene = new QGraphicsScene();
  QgsMapCanvasMap* mMap = new QgsMapCanvasMap(mpMapCanvas);
  mScene->addItem( mMap );
  mScene->update();
  QList<QGraphicsItem*> list = mScene->items();
  QList<QGraphicsItem*>::iterator it = list.begin();

  while ( it != list.end() ){
          QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem*>( *it );

          if(item){
                  item->updatePosition();
                  QMessageBox::information( this, tr( "TEST" ), tr( "Update
rendering" ) );
          }else{
//it will goes here.
                  QMessageBox::information( this, tr( "TEST" ), tr( "NOT
Update rendering" ) );
          }

          it++;
  }
}

from my reading,what i understand is i should use
QgsMapCanvasItem::updatePosition() to make my mapcanvas look like real-time.
Is it true? And i really hope you guys can teach me about how to implement
it in my code.


Thanks in advance,
Bonar
--
View this message in context: http://n2.nabble.com/Rendering-single-layer-from-mapcanvas-tp2968794p2968794.html
Sent from the qgis-developer mailing list archive at Nabble.com.

_______________________________________________
Qgis-developer mailing list
Qgis-developer@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/qgis-developer

_______________________________________________
Qgis-developer mailing list
Qgis-developer@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/qgis-developer
Reply | Threaded
Open this post in threaded view
|

AW: AW: Rendering single layer from mapcanvas

Hugentobler  Marco
Hi Ashish

To answer your questiones: the proposed solution was only meant for the display of a layer that is regularly updated. As you noted, it is only put on top of the map and it does not integrate with the legend and the normal tools. I think for this it would need support for updated layers implemented in the gui/app classes.
But even with my described plugin solution you could implement your own tools that work on the separate updated layer also in your plugin.

As updating a layer without repainting the others is a frequently asked question, I wrote once an (intentionally simple) example plugin that adds an independent layer on top of the QGIS map. You may download it from http://karlinapp.ethz.ch/updatelayer.tgz
But what I described is only one possible solution, there may be many others.

Regards,
Marco

-----Ursprüngliche Nachricht-----
Von: [hidden email] im Auftrag von ashjas
Gesendet: Do 09.07.2009 20:05
An: [hidden email]
Betreff: Re: AW: [Qgis-developer] Rendering single layer from mapcanvas
 

Hi Marco,

My requirement is also similar to what this post asks...

There are some doubts about ur method...please see if u can find time to
answer these..

would I be able to use all the mapTools like selection,identification etc on
the layer that i need to update constantly
by using your method (apart the normal static layers..)??

and can i add this live layer on to the legend and also set its symbology
from the layer property dialog box?

and i have a doubt about what u said .."In this subclass you need to create
a QgsVectorLayer.." so u mean that this subclass should have a
QgsVectorlayer object (or as many as the need may be for live layers) on
which i keep adding the live objects...and within this subclass i call the
paint method which will draw the objects??
and i guess i have to keep the same reference to the only Qgsmapcanvas
object for this subclass aswell as the objects are to be drawn only on the
mainCanvas.. and what about maprenderer object??should it be also the same
object as for the main layers??
and about implementing the paint method.. in short i would be calling the
drawFeature of the QgsVectorLayer Class(for all the features on the layer )
from within the paint function that would be custom implemented.. is it?

Please enlighten me..

Thanks for finding time and helping us.. :)

Best Regards.

Ashish


Hugentobler  Marco wrote:

>
> Hi Bonar
>
> QGIS renders the map into one image canvas item (QgsMapCanvasMap).
> Currently, it is not possible to refresh only one layer in this item.
> However, it is possible to render the content of the three layers that
> stay constant into a QgsMapCanvasMap (as you do now with all the four
> layers). For the layer that changes you could create a new canvas item (as
> a new subclass of QgsMapCanvasItem). In this subclass you need to create a
> QgsVectorLayer configured with your database instance . Then you could
> implement the paint method, there query all the features inside the view
> extent, use the transformation methods of QgsMapCanvasItem
> (toCanvasCoordinates()) and finally use QPainter to draw the objects as
> you want. Important is that the new item has the same size as the
> mapcanvas and also a transparent background such that you may see the
> content of the other three background layers.
>
> If then something in the datasource changes, you update your item class
> and only the item with one layer is repainted. The background with the
> three other layers stays the same.
>
>
> Regards,
> Marco
>
>  
>
>
> -----Ursprüngliche Nachricht-----
> Von: [hidden email] im Auftrag von bonar
> Gesendet: Mo 25.05.2009 11:41
> An: [hidden email]
> Betreff: [Qgis-developer] Rendering single layer from mapcanvas
>  
>
> Hi guys, Tim & Dr.Marco
>
> I was tried to display real-time data in my mapcanvas. In my mapcanvas, i
> have 4 layer, but i juz want to refresh 1 layer only(this layer retrieve
> data from PostGis) from the mapcanvas without refreshing all layer in the
> mapcanvas. I already searching from this forum and Google it, and the
> result
> is i should use QgsMapCanvasItem that have that capabilities to rendering
> single layer without refreshing mapcanvas. But, i don't know how to
> implement it in my application. I'm using sample application from Mr.Tim
> Sutton, it is a great tutorial for a beginner like me, and i think its
> better to include the code in here. This is what i already done:
>
>
> //Setting my layer
>
> mpMapCanvas= new QgsMapCanvas(0, 0);
>   mpMapCanvas->enableAntiAliasing(true);
>   mpMapCanvas->useImageToRender(true);
>   mpMapCanvas->setCanvasColor(QColor(255, 255, 255));
>   mpMapCanvas->freeze(false);
>   mpMapCanvas->setVisible(true);
>
>   QString myLayerPathNegeri         = LAYERPATH() + "klkv_state.shp";
>   QString myLayerBaseNameNegeri     = "klkv_state";
>   QString myProviderName            = "ogr";
>
>   QString myLayerPathDistrict         = LAYERPATH() + "klkv_district.shp";
>   QString myLayerBaseNameDistrict     = "klkv_district";
>
>   QString myLayerPathMukim         = LAYERPATH() + "klkv_mukim.shp";
>   QString myLayerBaseNameMukim     = "klkv_mukim";
>
> QString myLayerPathPoi         = "location_poi";
>   QString myLayerBaseNamePoi     = "location_poi";
>
> QgsVectorLayer * mypLayerNegeri = new QgsVectorLayer(myLayerPathNegeri,
> myLayerBaseNameNegeri, myProviderName);
>
>   QgsVectorLayer * mypLayerDistrict = new
> QgsVectorLayer(myLayerPathDistrict, myLayerBaseNameDistrict,
> myProviderName);
>
>   QgsVectorLayer * mypLayerMukim = new QgsVectorLayer(myLayerPathMukim,
> myLayerBaseNameMukim, myProviderName);
>
>   QgsVectorLayer * mypLayerPoi = new
> QgsVectorLayer(POSTGIS_LAYER_SETUP_INCIDENT_POI_FUNC(),
> myLayerBaseNamePoi,
> "postgres");
>
>
> QgsSingleSymbolRenderer *mypRendererNegeri = new
> QgsSingleSymbolRenderer(mypLayerNegeri->geometryType());
>   QList<QgsMapCanvasLayer> myLayerSet;
>   mypLayerNegeri->setRenderer(mypRendererNegeri);
>
>   QgsSingleSymbolRenderer *mypRendererDistrict = new
> QgsSingleSymbolRenderer(mypLayerDistrict->geometryType());
>   mypLayerDistrict->setRenderer(mypRendererDistrict);
>
>   QgsSingleSymbolRenderer *mypRendererMukim = new
> QgsSingleSymbolRenderer(mypLayerMukim->geometryType());
>   mypLayerMukim->setRenderer(mypRendererMukim);
>
>
> QgsSingleSymbolRenderer *mypRendererPoi = new
> QgsSingleSymbolRenderer(mypLayerPoi->geometryType());
>   mypLayerPoi->setRenderer(mypRendererPoi);
>
>
> QgsMapLayerRegistry::instance()->addMapLayer(mypLayerNegeri, TRUE);
>   QgsMapLayerRegistry::instance()->addMapLayer(mypLayerDistrict, TRUE);
>   QgsMapLayerRegistry::instance()->addMapLayer(mypLayerMukim, TRUE);
> QgsMapLayerRegistry::instance()->addMapLayer(mypLayerPoi, TRUE);
>
> myLayerSet.append(QgsMapCanvasLayer(mypLayerPoi));
> myLayerSet.append(QgsMapCanvasLayer(mypLayerMukim));
>   myLayerSet.append(QgsMapCanvasLayer(mypLayerDistrict));
>   myLayerSet.append(QgsMapCanvasLayer(mypLayerNegeri));
>
> mpMapCanvas->setLayerSet(myLayerSet);
>
>
> //I make a Qtimer to check if any update position for mypLayerPoi from
> updatingLocationPoiLayer() function
>
> QTimer *timerPoiRenderer = new QTimer(this);
>   connect(timerPoiRenderer, SIGNAL(timeout()), this,
> SLOT(updatingLocationPoiLayer()));
>   timerPoiRenderer->start(10 * 1000);// 10 seconds
>
>
> //this is how i tried to using QgsMapCanvasItem, sorry for the code
> because
> i am beginner for this QGis, so i juz try to play-around with the
> QgsMapCanvasItem code .
>
> void MyMain::updatingLocationPoiLayer()
> {
>
>   QGraphicsScene *mScene = new QGraphicsScene();
>   QgsMapCanvasMap* mMap = new QgsMapCanvasMap(mpMapCanvas);
>   mScene->addItem( mMap );
>   mScene->update();
>   QList<QGraphicsItem*> list = mScene->items();
>   QList<QGraphicsItem*>::iterator it = list.begin();
>
>   while ( it != list.end() ){
>           QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem*>( *it );
>
>           if(item){
>                   item->updatePosition();
>                   QMessageBox::information( this, tr( "TEST" ), tr(
> "Update
> rendering" ) );
>           }else{
> //it will goes here.
>                   QMessageBox::information( this, tr( "TEST" ), tr( "NOT
> Update rendering" ) );
>           }
>
>           it++;
>   }
> }
>
> from my reading,what i understand is i should use
> QgsMapCanvasItem::updatePosition() to make my mapcanvas look like
> real-time.
> Is it true? And i really hope you guys can teach me about how to implement
> it in my code.
>
>
> Thanks in advance,
> Bonar
> --
> View this message in context:
> http://n2.nabble.com/Rendering-single-layer-from-mapcanvas-tp2968794p2968794.html
> Sent from the qgis-developer mailing list archive at Nabble.com.
>
> _______________________________________________
> Qgis-developer mailing list
> [hidden email]
> http://lists.osgeo.org/mailman/listinfo/qgis-developer
>
> _______________________________________________
> Qgis-developer mailing list
> [hidden email]
> http://lists.osgeo.org/mailman/listinfo/qgis-developer
>
>

--
View this message in context: http://n2.nabble.com/Rendering-single-layer-from-mapcanvas-tp2968794p3233143.html
Sent from the qgis-developer mailing list archive at Nabble.com.
_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer

_______________________________________________
Qgis-developer mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/qgis-developer
Reply | Threaded
Open this post in threaded view
|

Re: AW: AW: Rendering single layer from mapcanvas

ashjas
Hi Marco...

Thanks for your inputs...

Regards,

Ashish

Hugentobler Marco wrote
Hi Ashish

To answer your questiones: the proposed solution was only meant for the display of a layer that is regularly updated. As you noted, it is only put on top of the map and it does not integrate with the legend and the normal tools. I think for this it would need support for updated layers implemented in the gui/app classes.
But even with my described plugin solution you could implement your own tools that work on the separate updated layer also in your plugin.

As updating a layer without repainting the others is a frequently asked question, I wrote once an (intentionally simple) example plugin that adds an independent layer on top of the QGIS map. You may download it from http://karlinapp.ethz.ch/updatelayer.tgz
But what I described is only one possible solution, there may be many others.

Regards,
Marco

-----Ursprüngliche Nachricht-----
Von: qgis-developer-bounces@lists.osgeo.org im Auftrag von ashjas
Gesendet: Do 09.07.2009 20:05
An: qgis-developer@lists.osgeo.org
Betreff: Re: AW: [Qgis-developer] Rendering single layer from mapcanvas
 

Hi Marco,

My requirement is also similar to what this post asks...

There are some doubts about ur method...please see if u can find time to
answer these..

would I be able to use all the mapTools like selection,identification etc on
the layer that i need to update constantly
by using your method (apart the normal static layers..)??

and can i add this live layer on to the legend and also set its symbology
from the layer property dialog box?

and i have a doubt about what u said .."In this subclass you need to create
a QgsVectorLayer.." so u mean that this subclass should have a
QgsVectorlayer object (or as many as the need may be for live layers) on
which i keep adding the live objects...and within this subclass i call the
paint method which will draw the objects??
and i guess i have to keep the same reference to the only Qgsmapcanvas
object for this subclass aswell as the objects are to be drawn only on the
mainCanvas.. and what about maprenderer object??should it be also the same
object as for the main layers??
and about implementing the paint method.. in short i would be calling the
drawFeature of the QgsVectorLayer Class(for all the features on the layer )
from within the paint function that would be custom implemented.. is it?

Please enlighten me..

Thanks for finding time and helping us.. :)

Best Regards.

Ashish


Hugentobler  Marco wrote:
>
> Hi Bonar
>
> QGIS renders the map into one image canvas item (QgsMapCanvasMap).
> Currently, it is not possible to refresh only one layer in this item.
> However, it is possible to render the content of the three layers that
> stay constant into a QgsMapCanvasMap (as you do now with all the four
> layers). For the layer that changes you could create a new canvas item (as
> a new subclass of QgsMapCanvasItem). In this subclass you need to create a
> QgsVectorLayer configured with your database instance . Then you could
> implement the paint method, there query all the features inside the view
> extent, use the transformation methods of QgsMapCanvasItem
> (toCanvasCoordinates()) and finally use QPainter to draw the objects as
> you want. Important is that the new item has the same size as the
> mapcanvas and also a transparent background such that you may see the
> content of the other three background layers.
>
> If then something in the datasource changes, you update your item class
> and only the item with one layer is repainted. The background with the
> three other layers stays the same.
>
>
> Regards,
> Marco
>
>  
>
>
> -----Ursprüngliche Nachricht-----
> Von: qgis-developer-bounces@lists.osgeo.org im Auftrag von bonar
> Gesendet: Mo 25.05.2009 11:41
> An: qgis-developer@lists.osgeo.org
> Betreff: [Qgis-developer] Rendering single layer from mapcanvas
>  
>
> Hi guys, Tim & Dr.Marco
>
> I was tried to display real-time data in my mapcanvas. In my mapcanvas, i
> have 4 layer, but i juz want to refresh 1 layer only(this layer retrieve
> data from PostGis) from the mapcanvas without refreshing all layer in the
> mapcanvas. I already searching from this forum and Google it, and the
> result
> is i should use QgsMapCanvasItem that have that capabilities to rendering
> single layer without refreshing mapcanvas. But, i don't know how to
> implement it in my application. I'm using sample application from Mr.Tim
> Sutton, it is a great tutorial for a beginner like me, and i think its
> better to include the code in here. This is what i already done:
>
>
> //Setting my layer
>
> mpMapCanvas= new QgsMapCanvas(0, 0);
>   mpMapCanvas->enableAntiAliasing(true);
>   mpMapCanvas->useImageToRender(true);
>   mpMapCanvas->setCanvasColor(QColor(255, 255, 255));
>   mpMapCanvas->freeze(false);
>   mpMapCanvas->setVisible(true);
>
>   QString myLayerPathNegeri         = LAYERPATH() + "klkv_state.shp";
>   QString myLayerBaseNameNegeri     = "klkv_state";
>   QString myProviderName            = "ogr";
>
>   QString myLayerPathDistrict         = LAYERPATH() + "klkv_district.shp";
>   QString myLayerBaseNameDistrict     = "klkv_district";
>
>   QString myLayerPathMukim         = LAYERPATH() + "klkv_mukim.shp";
>   QString myLayerBaseNameMukim     = "klkv_mukim";
>
> QString myLayerPathPoi         = "location_poi";
>   QString myLayerBaseNamePoi     = "location_poi";
>
> QgsVectorLayer * mypLayerNegeri = new QgsVectorLayer(myLayerPathNegeri,
> myLayerBaseNameNegeri, myProviderName);
>
>   QgsVectorLayer * mypLayerDistrict = new
> QgsVectorLayer(myLayerPathDistrict, myLayerBaseNameDistrict,
> myProviderName);
>
>   QgsVectorLayer * mypLayerMukim = new QgsVectorLayer(myLayerPathMukim,
> myLayerBaseNameMukim, myProviderName);
>
>   QgsVectorLayer * mypLayerPoi = new
> QgsVectorLayer(POSTGIS_LAYER_SETUP_INCIDENT_POI_FUNC(),
> myLayerBaseNamePoi,
> "postgres");
>
>
> QgsSingleSymbolRenderer *mypRendererNegeri = new
> QgsSingleSymbolRenderer(mypLayerNegeri->geometryType());
>   QList<QgsMapCanvasLayer> myLayerSet;
>   mypLayerNegeri->setRenderer(mypRendererNegeri);
>
>   QgsSingleSymbolRenderer *mypRendererDistrict = new
> QgsSingleSymbolRenderer(mypLayerDistrict->geometryType());
>   mypLayerDistrict->setRenderer(mypRendererDistrict);
>
>   QgsSingleSymbolRenderer *mypRendererMukim = new
> QgsSingleSymbolRenderer(mypLayerMukim->geometryType());
>   mypLayerMukim->setRenderer(mypRendererMukim);
>
>
> QgsSingleSymbolRenderer *mypRendererPoi = new
> QgsSingleSymbolRenderer(mypLayerPoi->geometryType());
>   mypLayerPoi->setRenderer(mypRendererPoi);
>
>
> QgsMapLayerRegistry::instance()->addMapLayer(mypLayerNegeri, TRUE);
>   QgsMapLayerRegistry::instance()->addMapLayer(mypLayerDistrict, TRUE);
>   QgsMapLayerRegistry::instance()->addMapLayer(mypLayerMukim, TRUE);
> QgsMapLayerRegistry::instance()->addMapLayer(mypLayerPoi, TRUE);
>
> myLayerSet.append(QgsMapCanvasLayer(mypLayerPoi));
> myLayerSet.append(QgsMapCanvasLayer(mypLayerMukim));
>   myLayerSet.append(QgsMapCanvasLayer(mypLayerDistrict));
>   myLayerSet.append(QgsMapCanvasLayer(mypLayerNegeri));
>
> mpMapCanvas->setLayerSet(myLayerSet);
>
>
> //I make a Qtimer to check if any update position for mypLayerPoi from
> updatingLocationPoiLayer() function
>
> QTimer *timerPoiRenderer = new QTimer(this);
>   connect(timerPoiRenderer, SIGNAL(timeout()), this,
> SLOT(updatingLocationPoiLayer()));
>   timerPoiRenderer->start(10 * 1000);// 10 seconds
>
>
> //this is how i tried to using QgsMapCanvasItem, sorry for the code
> because
> i am beginner for this QGis, so i juz try to play-around with the
> QgsMapCanvasItem code .
>
> void MyMain::updatingLocationPoiLayer()
> {
>
>   QGraphicsScene *mScene = new QGraphicsScene();
>   QgsMapCanvasMap* mMap = new QgsMapCanvasMap(mpMapCanvas);
>   mScene->addItem( mMap );
>   mScene->update();
>   QList<QGraphicsItem*> list = mScene->items();
>   QList<QGraphicsItem*>::iterator it = list.begin();
>
>   while ( it != list.end() ){
>           QgsMapCanvasItem* item = dynamic_cast<QgsMapCanvasItem*>( *it );
>
>           if(item){
>                   item->updatePosition();
>                   QMessageBox::information( this, tr( "TEST" ), tr(
> "Update
> rendering" ) );
>           }else{
> //it will goes here.
>                   QMessageBox::information( this, tr( "TEST" ), tr( "NOT
> Update rendering" ) );
>           }
>
>           it++;
>   }
> }
>
> from my reading,what i understand is i should use
> QgsMapCanvasItem::updatePosition() to make my mapcanvas look like
> real-time.
> Is it true? And i really hope you guys can teach me about how to implement
> it in my code.
>
>
> Thanks in advance,
> Bonar
> --
> View this message in context:
> http://n2.nabble.com/Rendering-single-layer-from-mapcanvas-tp2968794p2968794.html
> Sent from the qgis-developer mailing list archive at Nabble.com.
>
> _______________________________________________
> Qgis-developer mailing list
> Qgis-developer@lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/qgis-developer
>
> _______________________________________________
> Qgis-developer mailing list
> Qgis-developer@lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/qgis-developer
>
>

--
View this message in context: http://n2.nabble.com/Rendering-single-layer-from-mapcanvas-tp2968794p3233143.html
Sent from the qgis-developer mailing list archive at Nabble.com.
_______________________________________________
Qgis-developer mailing list
Qgis-developer@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/qgis-developer

_______________________________________________
Qgis-developer mailing list
Qgis-developer@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/qgis-developer