Как определить наведение курсора мыши на линейный график в Qt?

#c #qt #plot #qpainterpath

#c #qt #график #qpainterpath

Вопрос:

Я новичок в C , Qt и Visual Studio , и это мой первый пост о переполнении стека.

Заранее прошу прощения, если это повторяющийся вопрос, я пытался найти аналогичный вопрос, но не смог его найти. Дайте мне знать, если это повторный вопрос, и я удалю его.

Я пытаюсь создать линейный график с помощью QWidget::paintEvent() . Линейный график, который я рисую, на самом деле является QPainterPath . Я хочу определить, когда мышь наводится на мой линейный график, и поэтому я создаю небольшой прямоугольник, где находится мой курсор мыши, и определяю, когда этот прямоугольник пересекается с моим линейным графиком, используя bool QPainterPath::intersects() функцию. Проблема в том, что эта функция возвращает true, даже если моя мышь находится не совсем над моим линейным графиком. На изображении 1 (мне пока не разрешено вставлять изображения) мой линейный график представляет собой толстую черную кривую, и bool QPainterPath::intersects() возвращает значение true, даже когда мой курсор находится над желтой областью. Согласно документу Qt это потому, что:

Существует пересечение, если какая-либо из линий, составляющих прямоугольник, пересекает часть пути или если какая-либо часть прямоугольника перекрывается с любой областью, ограниченной путем.

Невозможно иметь QPainterPath без какой-либо замкнутой области, поскольку Qt предоставляет только два типа заливки для QPainterPath : Qt::OddEvenFill или Qt::WindingFill . (Честно говоря, я нахожу это своего рода раздражающим, поскольку открытый путь представляет собой серию отрезков, соединенных сквозным образом, если кто-то хочет охватить область, они могут легко соединить первую и последнюю точки, используя функции QPainterPath::lineTo() или QPainterPath::moveTo() )

В любом случае, я решил стать умнее Qt и нарисовал два дополнительных, QPainterPath где pathUp они находятся на несколько пикселей выше моего линейного графика и pathDn на несколько пикселей ниже моего линейного графика. На изображении 2 показаны эти 3 линейных графика: красный — pathUp , черный — реальный линейный график, а зеленый — pathDn . Я думал, что смогу обнаружить пересечение в QWidget::mouseMoveEvent() , используя следующий код:

 // cRect: Rectangle at mouse cursor position
if((pathUp.intersects(cRect) amp;amp; (!pathDn.intersects(cRect))) || ((!pathUp.intersects(cRect)) amp;amp; pathDn.intersects(cRect)))
{
    qDebug() << "Intersects";
}
  

Но это по-прежнему приводит к неправильным результатам, потому что теперь закрытая область отличается, как вы можете видеть на изображении 3, зеленая область — это закрытая область pathDn , а красная область — это закрытая область pathUp . Толстая черная кривая — это снова линейный график, на котором я хочу обнаружить наведение курсора мыши. На эту закрытую область не влияет Qt::setFillRule of QPainterPath .

Что еще более расстраивает, так это то, что я попробовал этот метод, используя QPolygonF вместо QPainterPath on QWidget , и результаты были точно такими же. Я также пробовал QGraphicsView , там я использовал QGraphicsPathItem для создания своего линейного графика, а затем использовал QGraphicsScene::focusItemChanged() signal для определения того, когда я нажимаю на свой линейный график. Это снова привело к тому же результату обнаружения щелчка, когда мой курсор находится над закрытой областью. Я не хочу создавать пользовательский QGraphicsItem (если мне это абсолютно не нужно) просто для переопределения его hoverEnterEvent() и hoverLeaveEvent() метода из-за ограничений, налагаемых на boundingRect() из QGraphicsItem , как описано в документах Qt:

QGraphicsScene ожидает, что все элементы boundingRect() и shape() останутся неизменными, если не будет получено уведомление. Если вы хотите каким-либо образом изменить геометрию элемента, вы должны сначала вызвать prepareGeometryChange(), чтобы разрешить QGraphicsScene обновлять свою бухгалтерию.

Поскольку я создаю график в режиме реального времени, boundingRect() будет меняться довольно часто (> 20 Гц), что приведет к дополнительной вычислительной нагрузке на программное обеспечение. Есть ли какой-либо способ решить мою проблему без создания пользовательского QGraphicsItem ?

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

Комментарии:

1. К вашему сведению, Qt уже предоставляет готовое решение Qt Charts .

2. Привет! да, я пробовал Qt Charts , но это довольно сложно, и я не могу добавить к нему дополнительные функции, которые мне нужны на моем графике. Другими словами, это довольно ограничительно. Кроме того, это медленно, и я хочу построить график QVector<doubles> длиной 100 000 за несколько 10 секунд миллисекунд.