Реклама

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

Спасибо большущее за советы! Все получилось через 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)
                }
            }
  • EVILEG
  • Ответ
  • 16 января 2018 г. 15:25

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

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

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

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

Спасибо, тоже нашел и получил значения благодаря 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
                }
            }

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
                }
            }
  • EVILEG
  • Статья
  • 16 января 2018 г. 7:19

Django - Урок 032. Расширенные параметры поиска

Django, Search

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

article = models.ForeignKey(Article, verbose_name=_("Статья"), null=True, blank=True)

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

Главным вопросом для меня было, как реализовать список тем на форуме так, чтобы не перегружать сайт дополнительными страницами, которые бы усложнили навигацию. Решение оказалось достаточно простым: добавить возможность поиска на форуме с дополнительными расширенными ключами поиска. А именно ключ article , который определял бы id статьи, по которому нужно отфильтровать все темы на форуме, которые содержат внешний ключ на статью с данным id .

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

  • MinusNull
  • Статья
  • 15 января 2018 г. 10:18

Шаблон программирования Pimpl - то, что вам следует знать

C++, Pimpl

Основы

Вы можете встретить шаблон Pimpl под другими именами: d-pointer, compiler firewall или даже шаблон Cheshire Cat или непрозрачный указатель.

В его основной форме шаблон выглядит следующим образом:

  • В классе мы перемещаем все закрытые члены в новый объявленный тип, например, в класс PrivateImpl .
  • Объявляем PrivateImpl в заголовочном файле основного класса.
  • В соответствующем файле cpp объявляем класс PrivateImpl и определяем его.
  • Теперь, если вы измените закрытую реализацию, код клиента не будет перекомпилирован (поскольку интерфейс не изменился).

Таким образом, это может выглядеть так (грубый, старый стиль кода!):

class.h

class MyClassImpl;
class MyClass {
    // ...
    void Foo();
private:    
    MyClassImpl* m_pImpl; // Предупреждение!!! 
                          // raw-указатель! :)
};

class.cpp

class MyClassImpl
{
public:
    void DoStuff() { /*...*/ }
};

MyClass::MyClass () 
: m_pImpl(new MyClassImpl()) 
{ }

MyClass::~MyClass () { delete m_pImpl; }

void MyClass ::DoSth() {
    m_pImpl->DoSth();
}

Эх ... уродливые raw-указатели!

Итак, кратко: мы упаковываем все, что является закрытым, в этот объявленный наперед класс. Мы используем только один член нашего основного класса - компилятор может работать только с указателем без полного объявления типа, поскольку необходим только размер указателя. Затем объявление и реализация происходят в файле .cpp .

Конечно, в современном C ++ рекомендуется использовать unique_ptr , а не raw-указатели.

Два очевидных недостатка этого подхода: нам нужно выделение памяти для хранения закрытой секции. А также основной класс просто перенаправляет вызов метода на закрытую реализацию.

Хорошо ... но это все ... верно? Не так просто!

Вышеприведенный код может работать, но мы должны добавить несколько бит, чтобы он работал в реальной жизни.

  • Rus6lan
  • Вопрос
  • 15 января 2018 г. 6:33

Проблема добавления #DEFINE при сборке CMak'ом

При сборке проекта появилась такая надпись:

Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example: - add -D_WIN32_WINNT=0x0501 to the compiler command line; or - add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.
Погуглив я попробовал и:
add_definitions(-D_WIN32_WINNT=0x0501)
и:
target_compile_definitions(SampleTnsClient PUBLIC _WIN32_WINNT=0x0501)
В обоих случаях получал ошибки(Это первая, но они однотипны):
4>PerformanceTest.obj : error LNK2001: unresolved external symbol "public: static void __cdecl boost::log::v2s_mt_nt5::record_view::public_data::destroy(struct boost::log::v2s_mt_nt5::record_view::public_data const *)" (?destroy@public_data@record_view@v2s_mt_nt5@log@boost@@SAXPEBU12345@@Z)
Код CMakeLists:
cmake_minimum_required(VERSION 3.7)

project(TNS_APP LANGUAGES CXX)

include(../thirdparties/liblinenoise-ng.cmake)

set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(APP_SOURCES "${SRC_DIR}/main.cpp"
                "${SRC_DIR}/SampleClientConfig.h"
                "${SRC_DIR}/SampleClientUtils.h"
                "${SRC_DIR}/SampleClientUtils.cpp"
                "${SRC_DIR}/Context.h"
                "${SRC_DIR}/Command.h"
                "${SRC_DIR}/Command.cpp"
                "${SRC_DIR}/SampleClientLog.h"
                "${SRC_DIR}/SampleClientLog.cpp"
                "${SRC_DIR}/PerformanceTest.h"
                "${SRC_DIR}/PerformanceTest.cpp"
                "${SRC_DIR}/SampleMessage.h"
                "${SRC_DIR}/SampleMessage.cpp"
                "${SRC_DIR}/SampleConsumer.h"
                "${SRC_DIR}/SampleConsumer.cpp"
                "${SRC_DIR}/DeliveryDelay.h"
                "${SRC_DIR}/DeliveryDelay.cpp"
                "${SRC_DIR}/PerformanceTestProfile.h"
                "${SRC_DIR}/PerformanceTestProfile.cpp"
                "${SRC_DIR}/PerformanceTestExecutor.h"
                "${SRC_DIR}/PerformanceTestExecutor.cpp"
                "${SRC_DIR}/SimplePositiveRandomGenerator.h"
                "${SRC_DIR}/SampleMessageProducer.h"
                "${SRC_DIR}/SampleMessageProducer.cpp"
                "${SRC_DIR}/SampleMessageAccumulator.h"
                "${SRC_DIR}/SampleMessageAccumulator.cpp")
                
add_executable(SampleTnsClient ${APP_SOURCES})
target_link_libraries(SampleTnsClient PRIVATE 
                        TnsClientLibrary 
                        Boost::program_options 
                        Boost::locale 
                        Boost::system 
                        Boost::filesystem 
                        Boost::log
                        liblinenoise-ng
                        librdkafkacpp 
                        librdkafka)
add_definitions(-D_WIN32_WINNT=0x0501)
find_program(PANDOC pandoc)
if(PANDOC)
  add_custom_target(SampleTnsClientDocs
    COMMAND pandoc "${SRC_DIR}/Readme.md" --latex-engine=xelatex -o "${CMAKE_CURRENT_BINARY_DIR}/Readme.pdf")
endif()

if(WIN32)
    target_compile_options(SampleTnsClient PRIVATE /wd4503 /wd4714)
endif()
  • alex_lip
  • Статья
  • 14 января 2018 г. 19:15

Разработка на Qt под iOS

ios, qt

Преамбула

Самая демократическая страна в мире создала самую тоталитарную операционную систему. Поэтому если вы хотите тестировать ваше ПО на IPad или IPhone вам нужно обязательно зарегистрироваться на сайте https://developer.apple.com/ в качестве разработчика. На первом этапе денег платить не обязательно. Добрый дядя Джобс даст вам сертификат, на использование для тестирования вашего же устройства, сроком на 7(семь) дней. По окончании действия сертификата ваше ПО не будет запускаться и его надо будет снова закачать с компа. Если вы захотите установить ваше ПО на устройство другого человека – его apple ID нужно будет точно так же прописать в Xcode как и ваш.

QGraphicsScene

хочу еще поблагодарить за помощь, я в свой проект это все внедрил, но вот строчка, что ниже, мне совсем не понятно как это работает:
// то пытаемся его отрисовать при условии, что он ещё не был отрисован
            auto it = std::find_if(m_tileItems.begin(), m_tileItems.end(), [&coordX1](const QGraphicsPixmapItem* pixmap) { return coordX1 == pixmap->pos().x(); } );
и еще, возникла проблема, когда я приближаю или отдаляю изображение, программа перестает работать (тайлы не грузятся)
    QMatrix matrix;
    matrix.scale(1.5,1.5);
    ui->graphicsView->setMatrix(matrix);
возможно вы подскажите, как сделать что бы программа работала и при зуме.
  • EVILEG
  • Комментарий
  • 10 января 2018 г. 11:20

QML - Урок 007. ListView Qml. Динамическое создание и удаление элементов

idshnik - это роль в модели данных.
Когда в QML в модель добавляются данные таким способом

listModel.append({idshnik: "Button " + (++number)})
То при попытке забрать данные из модели в QML вызывается во внутренностях ListView метод модели data() , который присутствует во всех моделях в Qt. Как я понимаю, в качестве роли передаётся QString ("idshnik") из делегата, и если в текущем объекте такая роль была найдена
{idshnik: "Button " + (++number)}
то возвращается некоторое значение, которое там было задано.
Реклама

C++ - Тест 003. Условия и циклы

  • Результат 35 баллов
  • Очки рейтинга -10
  • falcon
  • 16 января 2018 г. 17:25

Qt - Тест 001. Сигналы и слоты

  • Результат 100 баллов
  • Очки рейтинга 10
  • falcon
  • 16 января 2018 г. 17:22

Qt - Тест 001. Сигналы и слоты

  • Результат 68 баллов
  • Очки рейтинга -1
Последние комментарии

QML - Урок 021. Переключение между окнами в QML

Спасибо всем. Все получилось. Прикручиваю логику.

  • BlinCT
  • 14 января 2018 г. 19:28

Разработка на Qt под iOS

Вот честно, на сколько же муторно под огрызок что то делать. Куча проблем) А вод линь или под Андроид все просто и тривиально))

  • folax
  • 12 января 2018 г. 9:16

QML - Урок 021. Переключение между окнами в QML

Ничего сложного, делаете по тех заданию 3 файла qml, называете их как указанно в тех задании, потом из первого окна через Loader их переключаете, в окне 2 и 3 делаете сигналы которые при закры...

QML - Урок 021. Переключение между окнами в QML

Все верно, я и не говорил что этот кусок кода лично мое произведение. Это тоже верно: Это задание для прохождения на собеседование в одну из крупных украинских IT компаний. Логику ...

  • folax
  • 12 января 2018 г. 8:13

QML - Урок 021. Переключение между окнами в QML

int main(int argc, char *argv[]){ QApplication app(argc, argv); Logic logic; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("logic", &logic)...

Сейчас обсуждают на форуме
  • EVILEG
  • 18 января 2018 г. 20:46

Как проверить доступность сервера

Тут скорее всего ситуативно, но по факту да, в большинстве задач можно обойтись и одним network менеджером

  • EVILEG
  • 18 января 2018 г. 20:46

QGraphicsScene

Как вариант умножать ключевые координаты, от которых вы строите весь панораму, на общую ширину панорамы и при прокрутке отталкиваться от этих кратных координат.

  • Ruslan
  • 18 января 2018 г. 11:51

Исключения. Потоки.

Все оказалось проще. Документацию то читал, но забыл нюансы. Не указывал в connect  тип подключения Qt::DirectConnection

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

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

  • EVILEG
  • 15 января 2018 г. 17:21

Qt webgl

Насчёт проверки подключения клиента я не в курсе. Что касается экземпляров приложения, то из того, что я читал получается, что нет необходимости в нескольких экземплярах для нескольких кл...