Виталий Антипов
Виталий АнтиповJan. 16, 2018, 4:57 a.m.

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
                }
            }
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

8
Evgenii Legotckoi
  • Jan. 16, 2018, 9:07 a.m.
  • The answer was marked as a solution.

Добрый день!
Обработчик 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);
}
    Виталий Антипов
    • Jan. 16, 2018, 9:21 a.m.
    • (edited)

    Спасибо, тоже нашел и получил значения благодаря 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
      • Jan. 16, 2018, 9:38 a.m.
      • (edited)

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

        Виталий Антипов
        • Jan. 16, 2018, 9:46 a.m.

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

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

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

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

              Evgenii Legotckoi
              • Jan. 16, 2018, 10:25 a.m.
              • (edited)

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

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

                Спасибо большущее за советы! Все получилось через 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)
                                }
                            }

                  Comments

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

                  C ++ - Test 004. Pointers, Arrays and Loops

                  • Result:50points,
                  • Rating points-4
                  m

                  C ++ - Test 004. Pointers, Arrays and Loops

                  • Result:80points,
                  • Rating points4
                  m

                  C ++ - Test 004. Pointers, Arrays and Loops

                  • Result:20points,
                  • Rating points-10
                  Last comments
                  ИМ
                  Игорь МаксимовNov. 22, 2024, 11:51 a.m.
                  Django - Tutorial 017. Customize the login page to Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
                  Evgenii Legotckoi
                  Evgenii LegotckoiOct. 31, 2024, 2:37 p.m.
                  Django - Lesson 064. How to write a Python Markdown extension Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
                  A
                  ALO1ZEOct. 19, 2024, 8:19 a.m.
                  Fb3 file reader on Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
                  ИМ
                  Игорь МаксимовOct. 5, 2024, 7:51 a.m.
                  Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
                  d
                  dblas5July 5, 2024, 11:02 a.m.
                  QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
                  Now discuss on the forum
                  m
                  moogoNov. 22, 2024, 7:17 a.m.
                  Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
                  Evgenii Legotckoi
                  Evgenii LegotckoiJune 24, 2024, 3:11 p.m.
                  добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
                  t
                  tonypeachey1Nov. 15, 2024, 6:04 a.m.
                  google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
                  NSProject
                  NSProjectJune 4, 2022, 3:49 a.m.
                  Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

                  Follow us in social networks