Лучший способ создания длинного (или перекрестного) курсора в Qt GraphicsView - PullRequest
4 голосов
/ 15 января 2011

Простой способ создания курсора длинной перекрестной линии (до области просмотра) - создать перекрестную линию graphicsItem, при перемещении мыши установите свойство элемента pos.Но этот путь будет очень медленным, когда сцена сложная, потому что он должен обновить весь видовой экран, чтобы обновить pos.

Другой простой способ - setCursor(QCursor(..)), используйте QPixmap для определениядлинная перекрестная линия, этот путь будет очень быстрым, но курсор превысит прямоугольник области просмотра.

Есть ли другой способ быстро отобразить длинную перекрестную линию?

Большое спасибо!

Ответы [ 3 ]

10 голосов
/ 17 января 2011

Если я правильно понимаю, вы хотите нарисовать горизонтальную линию и вертикальную линию, пересекающую позицию курсора и имеющую размер окна просмотра.

Возможным решением будет переопределение QGraphicsScene :: drawForeground () чтобы нарисовать две линии с рисовальщиком.

Проблема в том, что сцена не знает о положении мыши.Это означает, что представление должно будет отслеживать его и информировать сцену об изменении положения мыши.

Для этого вам нужно будет создать свой собственный GraphicsScene (наследующий QGraphicsScene) и свой собственный.GraphicsView (наследует QGraphicsView).

В конструкторе GraphicsView вам нужно будет начать отслеживание мыши.Это заставит вас получать mouseMoveEvent каждый раз, когда мышь перемещается внутри вида:

GraphicsViewTrack::GraphicsViewTrack(QWidget* parent) : QGraphicsView(parent) {
    setMouseTracking(true);
}

void GraphicsViewTrack::mouseMoveEvent(QMouseEvent* pEvent) {
    QPointF MousePos = this->mapToScene(pEvent->pos());
    emit mousePosChanged(MousePos.toPoint());
}

Как видно из приведенного выше фрагмента кода, вид излучает сигнал (mousePosChanged) дляс которой сцена будет связана.Этот сигнал содержит положение мыши, преобразованное в координаты сцены.

Теперь на стороне сцены необходимо добавить слот, который будет вызываться при изменении положения мыши, сохранить новую позицию мыши в элементе.переменная и переопределение QGraphicsScene :: drawForeground () :

void GraphicsSceneCross::drawForeground(QPainter* painter, const QRectF& rect) {
    QRectF SceneRect = this->sceneRect();

    painter->setPen(QPen(Qt::black, 1));
    painter->drawLine(SceneRect.left(), m_MousePos.y(), SceneRect.right(), m_MousePos.y());
    painter->drawLine(m_MousePos.x(), SceneRect.top(), m_MousePos.x(), SceneRect.bottom());
}

void GraphicsSceneCross::onMouseChanged(QPoint NewMousePos) {
    m_MousePos = NewMousePos; // Store the mouse position in a member variable
    invalidate(); // Tells the scene it should be redrawn
}

Последнее, что нужно сделать, это подключить сигнал GraphicsView к слоту GraphicsScene.

Я позволюВы проверяете, является ли это решение приемлемым с точки зрения производительности.

1 голос
/ 16 сентября 2011

Основываясь на ответе Джерома и используя python, я создал этот код в своем подклассе QGraphicsScene:

def drawForeground(self, painter, rect):
    if self.guidesEnabled:
        painter.setClipRect(rect)
        painter.setPen(self.guidePen)
        painter.drawLine(self.coords.x(), rect.top(), self.coords.x(), rect.bottom())
        painter.drawLine(rect.left(), self.coords.y(), rect.right(), self.coords.y())

def mouseMoveEvent(self, event):
    self.coords = event.scenePos()
    self.invalidate()

Вам должно быть просто написать соответствующий код C ++. Обратите внимание, что я пользуюсь аргументом rect, переданным фреймворком Qt Api, и привязываю к нему художника область, так как это видимая область для рисования.

Я также кеширую объект пера, поскольку в других экспериментах я понял, что создание объектов во время рисования будет ухудшать производительность, и вы также даете пользователю возможность установить собственное перо в параметрах вашей программы.

0 голосов
/ 21 января 2011

Я нашел способ сделать это! Я работаю в системе Windows, поэтому могу использовать API с более низким GDI, выпрыгивая из системы рисования Qt. Деталь - получить HDC для viewPort в QGraphicsView. Затем в QMouseEvent из QGraphicsView используйте «MoveToEx» и «LineTo», рисуя две линии в области просмотра, затем я должен стереть «старый» курсор, это легко сделать с помощью «setROP2 (HDC dc, R2_NOT)», затем нарисуйте старый курсор, сохраненный снова. Этот метод не входит в систему QPainter, поэтому GraphicsItems под курсором не будут перерисовываться.

Чтобы решить проблему с заполнителем, когда мышь движется быстро, я не использую «двойной буфер». Я использовал QTimer для обновления курсора на холостом ходу процессора. Подробности в QMouseEvent, не обновляйте курсор вовремя, но сохраняйте позицию в списке. Когда процессор простаивает, нарисуйте курсор в списке позиций

Хотелось бы, чтобы это помогло тем, кто сталкивается со мной той же проблемой. Спасибо Жером, который дал мне полезный совет QGraphicsScene.

...