raptorswing / MapGraphics

A tile-based "slippy map" library written in/for C++/Qt. It's meant to enable C++/Qt developers to easily add nice, interactive maps to their applications. Supports zooming, rotating, interactive custom map objects, transparency, etc. It is a Qt map widget that can use tiles from MapQuest, Openstreetmap, or a custom source you define.
Other
164 stars 77 forks source link

Image could not be redrawn #32

Open xuniuer opened 2 years ago

xuniuer commented 2 years ago

Hi there,

I write a class VehicleObject, like CircleObject, inherited from MapGraphicsObject, to mark a vehicle position/state on map. The class will load a png file and paint in OSM tile map.

void VehicleObject::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option)
    Q_UNUSED(widget)

    painter->setRenderHint(QPainter::Antialiasing,true);
    painter->setPen(_fillColor);
    painter->drawPixmap(_img->rect(), *_img);
    qDebug() << "drawing: " << _img->rect() << "," << _img->size();
}

private member _img is declared as QPixmap*. Then I write a member function, like CircleObject class setRadius(qreal radius)

void VehicleObject::setVehicleState(VehicleState state, int direction) {
    QString png_file = QString(":/res/") + QString::number(state) + QString::number(direction) + QString(".png");
    _img->load(png_file); // load from resource file
    // here to fire redrawRequested()
    this->redrawRequested();
}

In TestApp, I prepare a timer to change VehicleObject state, like this

    QTimer* myTimer = new QTimer(this);
    MapGraphicsObject * vehicle = new VehicleObject();
    vehicle->setLatitude(40.9936234);
    vehicle->setLongitude(-112.202442);
    scene->addObject(vehicle);

    VehicleObject* vehicleCls = dynamic_cast<VehicleObject*>(vehicle);
    connect(myTimer, &QTimer::timeout, vehicleCls, [=](){
        int st = vehicleCls->state();
        if (st > VehicleIsWorking) st = VehicleIsIdle;
        else st++;

        int direction = vehicleCls->direction();
        if (direction > 350) direction = 0;
        else direction += 10;

        vehicleCls->setVehicleState(VehicleState(st), direction);
    });

    myTimer->start(1000);

In result, the png cannot be updated with timer's timeout event. However, the png file will change with mousewheel movement. Next, I use CircleObject to set with same logic except to change circle radius every 1 second, it works.

    CircleObject* circleCls = dynamic_cast<CircleObject*>(circle);
    connect(myTimer, &QTimer::timeout, circleCls, [=](){
        qreal r = circleCls->radius();
        qDebug() << "Current radius: " << r;
        circleCls->setRadius(r + 100);
    });

Any advice appreciated. Thanks.

xuniuer commented 2 years ago

I found a solution. in paint function, let widget to update manually, like this.

void VehicleObject::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option)
    // Q_UNUSED(widget)

    painter->setRenderHint(QPainter::Antialiasing,true);
    painter->setPen(_fillColor);
    painter->drawPixmap(_img->rect(), *_img);
    // explicitly, call widget update method
    widget->update();
}