Чертане на допълнителен елемент в QGraphicsItem по време на събитие при задържане на мишката

Бих искал да създам координатни точки на QGraphicsView. Когато мишката се задържи над точката, ще се покаже координатата.

Чертая координатите по QGraphicsEllipseItem. За да активирам събитието hover, трябва да внедря отново QGraphicsEllipseItem. Въпреки това, тъй като размерът на QGraphicsEllipseItem е фиксиран, когато е конструиран, текстът при задържане не се показва правилно. Как мога да се справя с това?

Ето моят код:

Основният прозорец:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    view = new QGraphicsView(this);
    view->setRenderHint(QPainter::Antialiasing);

    scene = new QGraphicsScene(this);
    view->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
    view->setScene(scene);
    setCentralWidget(view);

    for (int y = 0; y < 900; y += 100)
        for(int x = 0; x < 1400; x += 100)
            drawPoint(x, y);
}

void MainWindow::drawPoint(int x, int y)
{
    CoordinatePoint* point = new CoordinatePoint();
    point->setRect(QRect(x, y, 3, 3));
    point->setPen(QPen(Qt::red, 3, Qt::SolidLine));
    point->setBrush(Qt::red);
    scene->addItem(point);
}

Повторното внедряване на QGraphicsEllipseItem:

CoordinatePoint::CoordinatePoint(QGraphicsItem* parent)
    :QGraphicsEllipseItem(parent)
{
    setAcceptHoverEvents(true);
}


void CoordinatePoint::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
{
    hover = true;
    mx = event->pos().x();
    my = event->pos().y();
    update();
}

void CoordinatePoint::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
{
    hover = false;
    update();
}

void CoordinatePoint::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
    QGraphicsEllipseItem::paint(painter, option, widget);
    if (hover)
    {
        painter->save();
        painter->setPen(Qt::black);
        painter->setBrush(Qt::black);
        painter->drawText(mx + 2, my + 2,
                          "(" + QString::number(mx) + "," +
                          QString::number(my) + ")");
        painter->restore();
    }
}

person tom    schedule 31.10.2015    source източник


Отговори (1)


Мисля, че използването на отделен дъщерен елемент за текста ще направи живота ви много по-лесен:

#include <QtWidgets>

class CoordinatePoint : public QGraphicsEllipseItem
{
public:
    CoordinatePoint(QGraphicsItem* parent = Q_NULLPTR) :
        QGraphicsEllipseItem(parent),
        coordinateText(Q_NULLPTR)
    {
        setAcceptHoverEvents(true);
    }

    void hoverEnterEvent(QGraphicsSceneHoverEvent*)
    {
        if (!coordinateText) {
            coordinateText = new QGraphicsTextItem(this);
            coordinateText->setPlainText("(" + QString::number(x())
                + "," + QString::number(y()) + ")");
            coordinateText->setX(2);
            coordinateText->setY(2);
        }

        coordinateText->setVisible(true);
    }

    void hoverLeaveEvent(QGraphicsSceneHoverEvent*)
    {
        if (coordinateText) {
            coordinateText->setVisible(false);
        }
    }

private:
    QGraphicsTextItem *coordinateText;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QMainWindow window;

    QGraphicsView *view = new QGraphicsView(&window);
    view->setRenderHint(QPainter::Antialiasing);

    QGraphicsScene *scene = new QGraphicsScene(&window);
    view->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
    view->setScene(scene);
    window.setCentralWidget(view);

    for (int y = 0; y < 900; y += 100) {
        for(int x = 0; x < 1400; x += 100) {
            CoordinatePoint* point = new CoordinatePoint();
            point->setRect(QRect(0, 0, 3, 3));
            point->setX(x);
            point->setY(y);
            point->setPen(QPen(Qt::red, 3, Qt::SolidLine));
            point->setBrush(Qt::red);
            scene->addItem(point);
        }
    }

    window.show();

    return a.exec();
}

Ако наличието на допълнителен QGraphicsTextItem за всяка координата ви тревожи, можете да конструирате една от тях и просто да я споделите между всички тях, като я преобразувате, когато всяка от тях се задържа. Това трябва да работи добре, тъй като в даден момент може да има само една координата.

Ако се опитате да начертаете текста като част от елемента елипса, ще трябва да:

  • Увеличете размера на елемента, така че да е достатъчно голям, за да съдържа текста, което означава отмяна на boundingRect().
  • Начертайте елипсата само в рамките на определена част от тази област.
  • В hoverEnterEvent() проверете дали курсорът на мишката е в зоната на елипсата.
  • Вероятно куп други неща.
person Mitch    schedule 31.10.2015
comment
Благодаря, работи. Първоначално мислех, че ако създам QGraphicsTextItem с неговия родител да бъде друг QGraphicsitem, размерът е ограничен от QGraphicsitem. И се оказва погрешно. Има малък проблем: QGraphicsTextItem *coordinateText трябва да се инициализира до null_ptr, в противен случай програмата се срива. - person tom; 01.11.2015
comment
Инициализира се: coordinateText(Q_NULLPTR) - това срива ли се при вас? - person Mitch; 01.11.2015
comment
О, не съм забелязал да го правиш в конструктора - person tom; 02.11.2015