Select to view content in your preferred language

Movable Graphic in further versions of ArcGIS Qt

600
3
Jump to solution
08-16-2022 01:32 AM
Labels (2)
FatmaAkdemir
Occasional Contributor II

I want to ask if there is any feature plan for making the Graphic class movable via mouse move or drag event. It would be nice if we had an interface or a function like setMovable(true) and when we inherit from Graphic, our object would be movable on the map.

0 Kudos
1 Solution

Accepted Solutions
JamesBallard1
Esri Regular Contributor

Hi @FatmaAkdemir. There are some complications with that since it needs to cooperate with the MapView to know when and when not to pan the map in situations like this. Moving a graphic can be done now, although it's not as simple as having a clean interface with something like setMovable(true). I wrote some quick Qt Widgets sample code to show how.

connect(m_map, &Map::doneLoading, this, [this](Error)
{
  m_graphic = new Graphic(Point{0,0}, new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Square, QColor{Qt::red}, 10, this), this);
  auto overlay = new GraphicsOverlay(this);
  overlay->graphics()->append(m_graphic);
  m_mapView->graphicsOverlays()->append(overlay);
});

m_mapView = new MapGraphicsView(this);

// find the graphic from the clicked point
connect(m_mapView, &MapGraphicsView::identifyGraphicsOverlayCompleted, this, [this](QUuid, IdentifyGraphicsOverlayResult* identifyResult)
{
  const auto graphics = identifyResult->graphics();
  if (graphics.isEmpty())
    return;

  auto g = graphics.first();
  if (g == m_graphic)
  {
    m_movingGraphic = true;
  }
});

// if we found the graphic, start moving it to the new mouse location
connect(m_mapView, &MapGraphicsView::mouseMoved, this, [this](QMouseEvent& mouseEvent)
{
  if (!m_movingGraphic)
    return;

  auto newGeometry = m_mapView->screenToLocation(mouseEvent.x(), mouseEvent.y());
  m_graphic->setGeometry(newGeometry);
});

// "accept" the event to prevent dragging the MapView
// also start an identify to see if we clicked on the graphic
connect(m_mapView, &MapGraphicsView::mousePressed, this, [this](QMouseEvent& mouseEvent)
{
  mouseEvent.accept();
  m_mapView->identifyGraphicsOverlay(m_mapView->graphicsOverlays()->first(), mouseEvent.x(), mouseEvent.y(), 5, false);
});

// stop the dragging
connect(m_mapView, &MapGraphicsView::mouseReleased, this, [this](QMouseEvent&)
{
  m_movingGraphic = false;
}

 

Let me know if this works for your purposes.

View solution in original post

3 Replies
JamesBallard1
Esri Regular Contributor

Hi @FatmaAkdemir. There are some complications with that since it needs to cooperate with the MapView to know when and when not to pan the map in situations like this. Moving a graphic can be done now, although it's not as simple as having a clean interface with something like setMovable(true). I wrote some quick Qt Widgets sample code to show how.

connect(m_map, &Map::doneLoading, this, [this](Error)
{
  m_graphic = new Graphic(Point{0,0}, new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Square, QColor{Qt::red}, 10, this), this);
  auto overlay = new GraphicsOverlay(this);
  overlay->graphics()->append(m_graphic);
  m_mapView->graphicsOverlays()->append(overlay);
});

m_mapView = new MapGraphicsView(this);

// find the graphic from the clicked point
connect(m_mapView, &MapGraphicsView::identifyGraphicsOverlayCompleted, this, [this](QUuid, IdentifyGraphicsOverlayResult* identifyResult)
{
  const auto graphics = identifyResult->graphics();
  if (graphics.isEmpty())
    return;

  auto g = graphics.first();
  if (g == m_graphic)
  {
    m_movingGraphic = true;
  }
});

// if we found the graphic, start moving it to the new mouse location
connect(m_mapView, &MapGraphicsView::mouseMoved, this, [this](QMouseEvent& mouseEvent)
{
  if (!m_movingGraphic)
    return;

  auto newGeometry = m_mapView->screenToLocation(mouseEvent.x(), mouseEvent.y());
  m_graphic->setGeometry(newGeometry);
});

// "accept" the event to prevent dragging the MapView
// also start an identify to see if we clicked on the graphic
connect(m_mapView, &MapGraphicsView::mousePressed, this, [this](QMouseEvent& mouseEvent)
{
  mouseEvent.accept();
  m_mapView->identifyGraphicsOverlay(m_mapView->graphicsOverlays()->first(), mouseEvent.x(), mouseEvent.y(), 5, false);
});

// stop the dragging
connect(m_mapView, &MapGraphicsView::mouseReleased, this, [this](QMouseEvent&)
{
  m_movingGraphic = false;
}

 

Let me know if this works for your purposes.

FatmaAkdemir
Occasional Contributor II

Thank you @JamesBallard1 for this very clean solution. It is exactly the way we are currently moving our graphics right now. However if anything, any new functions or interfaces are added about this issue in the future, please let us know.

JamesBallard1
Esri Regular Contributor

@FatmaAkdemir another option to consider is using the SketchEditor. It might be overkill for your situation, but it supports graphics editing and simple moving of points and polygon vertices. It also has undo/redo support which might be useful.

0 Kudos