Название: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 21, 2023, 14:30 Всем привет.
Может кто подсказать, имеется обьект Rectangle с заданной шириной и длиной. И вот внутри него мне точно внутри него по границе надо нарисовать стрелку через Shape. Как понимаю можно через PathMultiline сделать. То есть нужно по ширине его занять, а по длине будет будет острый конец. Почему хочу нарисовать в rectangle, мне надо эту стрелку двигать, и если будет в rectangle то мне надо двигать его и точки у Shape не придется пересчитывать. Ну а вторйо вариант это прям в Shape нарисовать стрелку и пересчитывать все точки. Если у кого есть какой то пример буду признателен. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 21, 2023, 21:59 лично я вообще не понял как должна выглядеть эта стрелка и как/куда она будет двигаться. может картинка есть?
Название: Re: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 22, 2023, 09:19 лично я вообще не понял как должна выглядеть эта стрелка и как/куда она будет двигаться. может картинка есть? Вот на данном обьекте стрелка https://ibb.co/Dw6WqzC (https://ibb.co/Dw6WqzC) и она двигается по кругу в зависимости от текущего значения. Первая мысль это сделать прямоугольник с нужным значением в зависимости от размера всего обьекта, и поместить в него Shape. Но первое что не понятно так это как в С++ понять углы прямоугольника, где право а где лево. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 22, 2023, 10:59 надо было сказать «как в спидометре» :)
твой Rectangle — это внешняя черная окружность? не вижу чем рисование стрелки отличается от рисования любой из рисочек. ты знаешь угол наклона стрелки, а ее длина — это радиус большой окружности минус радиус маленькой. для анимации надо всего лишь угол стрелки изменить, что поменяет координаты ее Shape'а. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 22, 2023, 14:05 надо было сказать «как в спидометре» :) твой Rectangle — это внешняя черная окружность? не вижу чем рисование стрелки отличается от рисования любой из рисочек. ты знаешь угол наклона стрелки, а ее длина — это радиус большой окружности минус радиус маленькой. для анимации надо всего лишь угол стрелки изменить, что поменяет координаты ее Shape'а. Нет, rectangle при первом варианте внешнеи границы для стрелки. Будет прозрачным, при изменении значения меняется угол и перемещается невидимый rectangle. Пересчитывать точки в этмо случаи не надо. Но в этом случаи надо из qml передавать в С++ данные о rectangle.(я не знаю что нужно передавать чтоыб понимать как нарисовать внутри стрелку.) Другой вариант это зная какой размер у стрелки рисовать, и при измении пересчитывать все точки. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 22, 2023, 14:30 давай так. какие у тебя входные данные? т.е. по каким данным ты собираешься строить стрелку?
глядя на картинку, предполагаю, что у тебя всё нарисовано кроме стрелки (соответственно, в qml доступны все видимые объекты). из С++ будет приходить значение «скорости» от 0 до 1.2? «невидимый прямоугольник» — это ж просто координаты обрамляющего стрелку прямоугольника, насколько я понимаю? Название: Re: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 22, 2023, 14:40 давай так. какие у тебя входные данные? т.е. по каким данным ты собираешься строить стрелку? глядя на картинку, предполагаю, что у тебя всё нарисовано кроме стрелки (соответственно, в qml доступны все видимые объекты). из С++ будет приходить значение «скорости» от 0 до 1.2? «невидимый прямоугольник» — это ж просто координаты обрамляющего стрелку прямоугольника, насколько я понимаю? 1. Все размеры каждого обьекта это все из С++, и для ширины и длинны стрелки так же есть данные. Есть значение на которое стрелка должна будет поворачиватся, то есть для угла так же значения имеются. 2. Невидимы прямоугольник - как первый вариант что я описал выше да, это по сути было бы обрамлением. Но как я писал выше надо будет из qml послать нужные значения о нем в С++, получить все точки и массивом послать обратно. Но вот как определить левую и правую сторону его чтоыб стрелка правильно смотрела, это я вообще не моуг представить. Но при другмо варианте без прямоугольника нужно бы было высчитывать все точки не в прямоугольнике а в общем области тахометра. Это пока начальынй набросок кода. Код: Rectangle Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 22, 2023, 18:02 модифицируем предыдущий пример с отметками в часах (http://www.prog.org.ru/topic_33449_0.html) так, чтобы каждая отметка стала стрелочкой. по сути нам надо лишь добавить две линии (правый и левый кусок стрелки) в ShapePath. будем пользоваться теми же соображениями о полярных координатах: нам надо просто отклонить кусок стрелки от отметки на заданный угол (т.е. добавить или вычесть угол стрелки из угла отметки). также для удобства вычислений введем функции конвертации полярных координат в обычные (декартовы).
в твоем случае стрелка двумерная, но это ничего принципиально не меняет. кончик стрелки как раз будет указывать на отметку. зачем тебе передавать координаты стрелки в С++ я не очень понял, ты ж можешь наоборот их оттуда и брать. надеюсь, суть подхода ясна :) как видишь, никакие стороны для стрелки определять отдельно не надо, всё работает «само по себе». Код
Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 22, 2023, 18:41 а чтоб в С++ вычислять координаты, задай свою стрелку для случая в 0 градусов (смотрит вправо, на 3 часа) как QPolygonF, а потом просто вращай ее на нужный угол с помощью QTransform
Название: Re: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 22, 2023, 20:03 Может быть я не правильно понимаю ваш пример кода, но все тикмарки стали стрелками?)
Мне же надо 1 стрелку сделать, https://ibb.co/2Mj9qX6 (https://ibb.co/2Mj9qX6) вот она. Я по этому и писал что стрелка это 5 точек. По этому и писал про 2 варианта создания стрелки, или внутри rectangle и его поворачивать по нужному углу, или без rectangle но тогда все точки пересчитывать. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 22, 2023, 20:13 То что я кидал картинку выше это рисунок к которому я стараюсь данный обьект привести. И на нем у меня 2 последние проблемы, это сама стрелка именно такого вида, именно она короткая. И такст что у мажорных тикмарков написана, но это уже совсем другая история.
Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 22, 2023, 22:09 Может быть я не правильно понимаю ваш пример кода, но все тикмарки стали стрелками?) да. это сделано для примера, т.к. я подумал, что у тебя трудности с рисованием кончика твоей стрелки (диагональных линий). адаптировать уже надо самому :)или без rectangle но тогда все точки пересчитывать. ну тут вопрос откуда ты хочешь координаты стрелки брать. раз ты говоришь, что тебе в итоге их все равно надо в С++ отправить, то проще там сразу их и вычислить как я написал выше (и не придется трогать полярные координаты), а в QML просто нарисовать Shape/ShapePath по вычисленным координатам (можно забайндить на свойство С++ объекта, которое будет отдавать полигон, тогда все будет работать автоматически, без какого-либо императивного жс кода). Shape — это ведь Item со всеми вытекающими, поэтому непонятно зачем нужен дополнительный невидимый Rectangle.То что я кидал картинку выше это рисунок к которому я стараюсь данный обьект привести. И на нем у меня 2 последние проблемы, это сама стрелка именно такого вида, именно она короткая. как короткую нарисовать я уже писал выше (длина = радиус1 - радиус2), да и это ж ровно то же самое, что и отметки рисовать, просто линия не одна.в твоем примере кода стрелка — это Rectangle, но ведь можно ее сразу Shape делать. Да и координаты там явно как-то должны зависеть от размера рута. до сих пор не могу понять в чем именно у тебя проблема :) айтем стрелки нарисовать? повернуть его можно через свойство rotation / transform. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 22, 2023, 22:43 Кончик стрелки в любом случаи не вариант как мне кажется так рисовать, потмоу что внутри будет заливатся цветом и я нашел вот это
Код: PathPolyline { То есть те самые 5 точек из которых должна получистя стрелка. Могли бы показать примером такую стрелку, предположим длинна 12, ширина 5, конец стрелки например 20% от длинны. И например угол для поварота 75 градусов. С таким примером я бы понял как можно модифицировать. И да, все расчеты в С++ будут, а точнее есть. Но не для стрелки. И такой вопрос, в вашем примере 2 раза PathMove но на них не завязаны сами PathLine. Как они законекчены друг с другом? Спасибо Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 23, 2023, 10:39 да, можно стрелку и через PathPolyline нарисовать (можно и через набор PathLine).
И такой вопрос, в вашем примере 2 раза PathMove но на них не завязаны сами PathLine. Как они законекчены друг с другом? они как раз завязаны, рисование выполняется последовательно от «текущей точки». мы начинаем с границы окружности и рисуем рисочку, текущая точка становится концом рисочки. но оба куска стрелки мы хотим начать с границы окружности, поэтому возвращаемся в исходную точку 0,0.вот пример. здесь мы определяем размер стрелки через относительные величины, а потом масштабируем ее до нужного размера через scale (можно и сразу задавать координаты с учетом размера, это не столь существенно). также тут есть небольшая хитрость: стрелка приклеена к маленькой окружности (для случая в 0 градусов), а дальше мы просто выполняем вращение этой окружности, чтоб установить стрелку в нужное положение. в качестве альтернативы можно окружность не вращать, а вращать эфемерный айтем-родитель для стрелки (он будет иметь anchors.fill: smallCircle). но если ты будешь в коде считать координаты заранее, то в этой хитрости нет необходимости. Код просто добавить этот элемент после репитера. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 23, 2023, 19:18 Спасибо за пример, в принципе я понял немного его.
Но исходя из того как приходится мне считать в С++ точки для стрелки остаются пара вопросов: стрелка это 5 точек, 1 и 5 это начало и конец, то есть одинаковые точки. 1 и 2 точки они рядом с центральной окружностью, и угол на котором они должны быть в направлении нужного значения это половина отрезка между ними. Как лучше их расчитывать если знаем длинну и ширину? Все 5 точек на одном углу, потом за счет размера их рапределять? То есть 1 и 2 точки это ширина стрелки а значит от угла сдвигать на половину? Или так расчитывать не правильно? Это 2 функции что я написал для использования. Код: QPointF needle::calculatePoint(const double& radius, const double& angle) одна функция расчитывает угол иходя их текущего значения и диапазона значений между которыми лежит, и другая функция получает расчитанный угол и радиус. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 23, 2023, 19:47 Цитировать угол на котором они должны быть в направлении нужного значения это половина отрезка между ними угол не может равняться половине отрезка, это разные величиныкак я понимаю, calculatePoint вычисляет точку на маленькой окружности. по идее тебе достаточно добавить эту точку к каждой точке стрелки, при условии, что стрелка задана в относительных координатах, где (0,0) — это правый край маленькой окружности. также можно задать стрелку для 0 градусов, а потом просто применять к ней QTransform-поворот вместо своих вычислений: Код можно такой поворот и к каждой отдельной точке применить при необходимости З.Ы. лучше передавать double по значению Название: Re: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 23, 2023, 19:56 как я понимаю, calculatePoint вычисляет точку на маленькой окружности. по идее тебе достаточно добавить эту точку к каждой точке стрелки, при условии, что стрелка задана в относительных координатах, где (0,0) — это правый край маленькой окружности. Не совсем, calculatePoint в случаи тикмарков высчитывает для них начало и конец, то есть 2 точки. И эту же функцию я и хотел использовать чтобы высчитывать каждую точку стрелки. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 23, 2023, 21:36 а, ну да, там можно получить любую точку на луче, главное правильный радиус передать
Название: Re: Нарисовать стрелку внутри rectangle Отправлено: SektorCT от Июль 25, 2023, 17:17 Найден неплохой вариант, нахожденеи точек с отступом от центра стрелки, то есть нахождение угла наклона и после от него считать.
Вдруг кому пригодится. Код: QPointF calculatePoint(const double& radius, const double& angle, const double& offset) Офсет в данном случаи надо считать на сколько в бок отходят точки. Название: Re: Нарисовать стрелку внутри rectangle Отправлено: kambala от Июль 25, 2023, 21:42 нагуглил или геометрически вывел? :) так вот сходу неочевидно откуда взялась формула. UPD: а, понял, это ж матрица поворота (и вот мы опять пришли к QTransform :) ), а offset — это по сути ненулевая у-координата у точек по обе стороны центра стрелки.
можно немного улучшить код: Код
|