Виталий Антипов
Виталий Антипов16 січня 2018 р. 04:57

ChartView. Отображение метки данных точки серии при наведении курсора

Добрый день! Подскажите, как отобразить метки данных точки в LineSeries при наведении курсора? Из документации понял, что перехватить событие наведения можно через onHovered(), но как получить индекс/позицию/значение нужной точки?

ChartView {
                id: chartIzmerHh
                objectName: "chartIzmerHh"
                property int count
                property var array_dateX
                property var array_valueY
                property var array_valueY1
                property var array_valueY2
                visible: true
                anchors.top: rec_filter.bottom
                anchors.left: parent.left
                anchors.right: parent.right
                anchors.bottom: parent.bottom
                antialiasing: true
                legend.visible: false
                title: "Средняя вибрация на холостом ходу"
                ValueAxis {
                    id: axiY
                    min: 0
                }
                DateTimeAxis {
                    id: axiX
                    format: "dd-MM-yyyy"
                    min: rec_filter.date_begin
                    max: rec_filter.date_end
                }
                LineSeries {
                    id: line1
                    property bool myBool: false
                    color: "lightgreen"
                    axisY: axiY
                    axisX: axiX
                    width: 5
                    onHovered: {
                       // ???
                    }
                }
                LineSeries {
                    id: line2
                    color: "tomato"
                    axisY: axiY
                    axisX: axiX
                    width: 5
                }
                LineSeries {
                    id: line
                    color: "#03a9f5"
                    axisY: axiY
                    axisX: axiX
                    width: 5
                }
                Component.onCompleted: {
                    var xx = []
                    var yy = []
                    var yy1 = []
                    var yy2 = []
                    var max = 0
                    for(var i=0;i<count;i++){
                        xx[i] = Date.parse(array_dateX[i])
                        yy[i] = Number(array_valueY[i])
                        yy1[i] = Number(array_valueY1[i])
                        yy2[i] = Number(array_valueY2[i])
                        if(yy[i]>max){
                            max = yy[i]
                        }
                        if(yy1[i]>max){
                            max = yy1[i]
                        }
                        if(yy2[i]>max){
                            max = yy2[i]
                        }
                        line.append(xx[i], yy[i])
                        line1.append(xx[i], yy1[i])
                        line2.append(xx[i], yy2[i])
                    }
                    max = Math.round(max) + 1
                    axiY.max = max
                }
            }
Рекомендуємо хостинг TIMEWEB
Рекомендуємо хостинг TIMEWEB
Стабільний хостинг, на якому розміщується соціальна мережа EVILEG. Для проектів на Django радимо VDS хостинг.

Вам це подобається? Поділіться в соціальних мережах!

8
Evgenii Legotckoi
  • 16 січня 2018 р. 09:07
  • Відповідь була позначена як рішення.

Добрый день!
Обработчик onHovered навешивается автоматически на сигнал hovered.

В документации дана следующая сигнатура этого сигнала
hovered(point point, bool state)
Вот описание из документации

This signal is emitted when a mouse is hovered over the point point in the chart. When the mouse moves over the point, state turns true , and when the mouse moves away again, it turns false .

Соответственно обработчик можно написать так
onHovered: {
    console.log(point);
    console.log(point.x);
    console.log(point.y);
    console.log(state);
}
    Виталий Антипов
    • 16 січня 2018 р. 09:21
    • (відредаговано)

    Спасибо, тоже нашел и получил значения благодаря point.x и point.y. Отформатировал значение даты и вывел искомые значения в прямоугольник. Теперь столкнулся с проблемой перемещения прямоугольника к курсору мыши при срабатывании onHovered(). Использовать MouseArea и брать оттуда mouseX и mouseY не вариант, так как MouseArea перекроет LineSeries и события onHovered никогда не получим. Подскажите, есть какие-нибудь варианты решить проблему?

    ChartView {
                    id: chartIzmerHh
                    objectName: "chartIzmerHh"
                    property int count
                    property var array_dateX
                    property var array_valueY
                    property var array_valueY1
                    property var array_valueY2
                    visible: false
                    anchors.top: rec_filter.bottom
                    anchors.left: parent.left
                    anchors.right: parent.right
                    anchors.bottom: parent.bottom
                    antialiasing: true
                    legend.visible: false
                    title: "Средняя вибрация на холостом ходу"
                    Rectangle {
                        id: rec_hovered
                        color: "yellow"
                        width: text_hovered1.width
                        height: text_hovered1.height + text_hovered2.height
                        Text {
                            id: text_hovered1
                            anchors.bottom: text_hovered2.top
                            text: line1.date_x //сюда выводим значение x при срабатывании onHovered
                        }
                        Text {
                            id: text_hovered2
                            anchors.bottom: parent.bottom
                            text: line1.value_y ////сюда выводим значение y при срабатывании onHovered
                        }
                    }
                    ValueAxis {
                        id: axiY
                        min: 0
                    }
                    DateTimeAxis {
                        id: axiX
                        format: "dd-MM-yyyy"
                        min: rec_filter.date_begin
                        max: rec_filter.date_end
                    }
                    LineSeries {
                        id: line1
                        property string date_x
                        property string value_y
                        color: "lightgreen"
                        axisY: axiY
                        axisX: axiX
                        width: 5
                        onHovered: {
                            var d = new Date(point.x),                    //форматируем дату
                            month = '' + (d.getMonth() + 1),
                            day = '' + d.getDate(),
                            year = d.getFullYear();
                            if (month.length < 2) month = '0' + month;
                            if (day.length < 2) day = '0' + day;
                            date_x = ([day, month, year].join('-')).toString()
                            value_y = ((point.y).toFixed(2)).toString()   //форматируем значение по y
                        }
    
                    }
                    LineSeries {
                        id: line2
                        color: "tomato"
                        axisY: axiY
                        axisX: axiX
                        width: 5
                    }
                    LineSeries {
                        id: line
                        color: "#03a9f5"
                        axisY: axiY
                        axisX: axiX
                        width: 5
                    }
                    Component.onCompleted: {
                        var xx = []
                        var yy = []
                        var yy1 = []
                        var yy2 = []
                        var max = 0
                        for(var i=0;i<count;i++){
                            xx[i] = Date.parse(array_dateX[i])
                            yy[i] = Number(array_valueY[i])
                            yy1[i] = Number(array_valueY1[i])
                            yy2[i] = Number(array_valueY2[i])
                            if(yy[i]>max){
                                max = yy[i]
                            }
                            if(yy1[i]>max){
                                max = yy1[i]
                            }
                            if(yy2[i]>max){
                                max = yy2[i]
                            }
                            line.append(xx[i], yy[i])
                            line1.append(xx[i], yy1[i])
                            line2.append(xx[i], yy2[i])
                        }
                        max = Math.round(max) + 1
                        axiY.max = max
                    }
                }

      Evgenii Legotckoi
      • 16 січня 2018 р. 09:38
      • (відредаговано)

      Пока мыслей нет, но попробуйте всё-таки MouseArea. Дело в том, что у неё есть свойство propagateComposedEvents , которое по умолчанию установлено на false , а если его установить на true, то события должны передаваться на объекты, которые перекрываются этой самой MouseArea.

        Виталий Антипов
        • 16 січня 2018 р. 09:46

        Спасибо, попробую! Тут еще вариант придумал - создать ScatterSeries и при onHovered создать точку с требуемыми координатами. Попробовал scatter.append(point.x, point.y) - получается очень красиво. Только надо изучить как ее заменять на новую и как форматировать значения pointLabels

          Evgenii Legotckoi
          • 16 січня 2018 р. 10:04

          У ScatterSeries есть методы

          • remove(int index),
          • remove(real x, real y),
          • removePoints(int index, int count)
          Если будете оперировать только одной точкой в каждом графике ScatterSeries для каждой LineSeries (то есть один ScatterSeries для одной LineSeries ), то удалять можно будет точку по индекс при каждом срабатывании onHovered , то есть scatter1.remove(0), а потом просто добавлять новую точку. Ну или наверняк можно просто изменить координаты точки через метод replace.
            Виталий Антипов
            • 16 січня 2018 р. 10:10

            Спасибо за ответ! Кстати, propagateComposedEvents: true не дает получить событие onHovered .

              Evgenii Legotckoi
              • 16 січня 2018 р. 10:25
              • (відредаговано)

              Если честно у меня пока только одна идиотская идея есть. Брать по таймеру текущую позицию курсора глобально из C++ специальным классом. И этот класс будет зарегистрирован в QML, у него будет сигнал, который будет высылать информацию о положении курсора, что позволит обновлять информацию так, как вам будет нужно (используя конечно манипуляции с мапингом глобальных координат в координаты графика).

              Ещё я бы рекомендовал покапаться в исходниках, хотя бы заголовочных файлах QQuickItem, от которого, по моему мнению, должен быть наследован ChartView в результате. Дело в том, что в официальной документации нет полного описания всех методов, которыми обладают Quick компоненты, я это заметил, когда разбирался с написанием кастомных Quick компонентов и использованием OpenGL в них. Часто приходилось заглядывать в заголовочники того же самого QQuickItem и не все публичные методы были описаны в документации.
                Виталий Антипов
                • 16 січня 2018 р. 11:47

                Спасибо большущее за советы! Все получилось через ScatterSeries. Методы remove() как-то сходу не дались, удаляет в первый раз, а потом программа падает... Не стал тратить время и воспользовался методом replace(). Все идеально, работает шустро! Еще раз спасибо!

                ChartView {
                                id: chartIzmerHh
                                objectName: "chartIzmerHh"
                                property int count
                                property var array_dateX
                                property var array_valueY
                                property var array_valueY1
                                property var array_valueY2
                                property real oldX        //сюда записываем координату текущей точки scatter для метода replace()
                                property real oldY        //сюда записываем координату текущей точки scatter для метода replace()
                                visible: false
                                anchors.top: rec_filter.bottom
                                anchors.left: parent.left
                                anchors.right: parent.right
                                anchors.bottom: parent.bottom
                                antialiasing: true
                                legend.visible: false                
                                title: "Средняя вибрация на холостом ходу"
                                ValueAxis {
                                    id: axiY
                                    min: 0
                                }
                                DateTimeAxis {
                                    id: axiX
                                    format: "dd-MM-yyyy"
                                    min: rec_filter.date_begin
                                    max: rec_filter.date_end
                                }
                                LineSeries {
                                    id: line1
                                    property string date_x
                                    property string value_y
                                    color: "lightgreen"
                                    axisY: axiY
                                    axisX: axiX
                                    width: 5
                                    onHovered: {
                //форматируем дату по x и значение по y
                                        var d = new Date(point.x),
                                        month = '' + (d.getMonth() + 1),
                                        day = '' + d.getDate(),
                                        year = d.getFullYear();
                                        if (month.length < 2) month = '0' + month;
                                        if (day.length < 2) day = '0' + day;
                                        date_x = ([day, month, year].join('-')).toString()
                                        value_y = ((point.y).toFixed(2)).toString()
                //заменяем старую точку на новую
                                        scatter.replace(chartIzmerHh.oldX, chartIzmerHh.oldY, point.x, point.y)
                //перезаписываем текущие координаты, они станут старыми при следующем вызове onHovered и уйдут в replace()
                                        chartIzmerHh.oldX = point.x
                                        chartIzmerHh.oldY = point.y
                                    }
                                }
                                ScatterSeries {
                                    id: scatter
                                    pointLabelsVisible: true
                                    pointLabelsClipping: false
                                    pointLabelsFont: bold
                                    pointLabelsFormat: "" + line1.value_y +" ; "+ line1.date_x + ""  //сюда пишем отформатированные текущие значения
                                    color: "lightgreen"
                                    borderColor: "black"
                                    axisY: axiY
                                    axisX: axiX
                                }
                                LineSeries {
                                    id: line2
                                    color: "tomato"
                                    axisY: axiY
                                    axisX: axiX
                                    width: 5
                                }
                                LineSeries {
                                    id: line
                                    color: "#03a9f5"
                                    axisY: axiY
                                    axisX: axiX
                                    width: 5
                                }
                                Component.onCompleted: {
                                    var xx = []
                                    var yy = []
                                    var yy1 = []
                                    var yy2 = []
                                    var max = 0
                                    for(var i=0;i<count;i++){
                                        xx[i] = Date.parse(array_dateX[i])
                                        yy[i] = Number(array_valueY[i])
                                        yy1[i] = Number(array_valueY1[i])
                                        yy2[i] = Number(array_valueY2[i])
                                        if(yy[i]>max){
                                            max = yy[i]
                                        }
                                        if(yy1[i]>max){
                                            max = yy1[i]
                                        }
                                        if(yy2[i]>max){
                                            max = yy2[i]
                                        }
                                        line.append(xx[i], yy[i])
                                        line1.append(xx[i], yy1[i])
                                        line2.append(xx[i], yy2[i])                        
                                    }
                //ставим сразу точку на график (меня интересует последняя) и записываем ее текущее значение, которое потом уйдет в replace()
                                    oldX = xx[count-1]
                                    oldY = yy1[count-1]
                                    scatter.append(xx[count-1], yy1[count-1])
                                    max = Math.round(max) + 1
                                    axiY.max = max
                                    console.log(oldX,oldY)
                                }
                            }

                  Коментарі

                  Only authorized users can post comments.
                  Please, Log in or Sign up
                  AD

                  C++ - Тест 004. Указатели, Массивы и Циклы

                  • Результат:50бали,
                  • Рейтинг балів-4
                  m
                  • molni99
                  • 26 жовтня 2024 р. 11:37

                  C++ - Тест 004. Указатели, Массивы и Циклы

                  • Результат:80бали,
                  • Рейтинг балів4
                  m
                  • molni99
                  • 26 жовтня 2024 р. 11:29

                  C++ - Тест 004. Указатели, Массивы и Циклы

                  • Результат:20бали,
                  • Рейтинг балів-10
                  Останні коментарі
                  ИМ
                  Игорь Максимов22 листопада 2024 р. 22:51
                  Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                  Evgenii Legotckoi
                  Evgenii Legotckoi01 листопада 2024 р. 00:37
                  Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                  A
                  ALO1ZE19 жовтня 2024 р. 18:19
                  Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                  ИМ
                  Игорь Максимов05 жовтня 2024 р. 17:51
                  Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                  d
                  dblas505 липня 2024 р. 21:02
                  QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                  Тепер обговоріть на форумі
                  Evgenii Legotckoi
                  Evgenii Legotckoi25 червня 2024 р. 01:11
                  добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                  t
                  tonypeachey115 листопада 2024 р. 17:04
                  google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                  NSProject
                  NSProject04 червня 2022 р. 13:49
                  Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
                  9
                  9Anonim25 жовтня 2024 р. 19:10
                  Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

                  Слідкуйте за нами в соціальних мережах