Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Alexu007 от Июля 13, 2014, 14:53



Название: Рисование на форме.
Отправлено: Alexu007 от Июля 13, 2014, 14:53
Допустим я хочу нарисовать на форме ломаную линию, чтобы при каждом нажатии кнопки добавлялось следующее звено. Для этого я пишу код:

Код
C++ (Qt)
void Widget::paintEvent(QPaintEvent *event)
{
   QPainter p(this);
   p.drawLine(x1, x2, y1, y2);
}
 
 
// обработка нажатия кнопки
void Widget::MyEventHandler1()
{
   static uint Cx = 0;
 
   switch(Cx)
   {
       case 0: {x1 = x2 = 20; y1 = y2 = 80; break;}
       case 1: {x1 = y1; x2 = y2; y1 = 160, y2 = 20; break;}
       case 2: {x1 = y1; x2 = y2; y1 = 240, y2 = 80; break;}
 
   }
 
   Cx++;
   this->repaint();
}

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


Название: Re: Рисование на форме.
Отправлено: Old от Июля 13, 2014, 14:56
Сохранять каждое звено в списочек и рисовать весь список.


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 13, 2014, 15:22
А если что-нить посложнее ломаной линии - синусоида, например? Нужно сохранять в список каждую точку синусоиды?
А попроще способа нету?


Название: Re: Рисование на форме.
Отправлено: Old от Июля 13, 2014, 15:24
А если что-нить посложнее ломаной линии - синусоида, например? Нужно сохранять в список каждую точку синусоиды?
А попроще способа нету?
Рисуйте на QImage и показывайте его.


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 13, 2014, 22:11
Ну вот есть специальный компонент для графики GraphicsView и scene - класс для работы с 2d графикой - вроде то, что нужно.
http://habrahabr.ru/sandbox/54215/

Немогу понять, как задавать координаты для scene->addLine(0,90,180,90,pen); Какие бы я координаты не задавал - все линии идут через центр. Где на scene точка с координатой 0,0 и, и например 100,200? Как нарисовать линию, идущую не через центр, например (0,10,100,10)? Чё за фигня, или это я тупой?


Название: Re: Рисование на форме.
Отправлено: Bepec от Июля 13, 2014, 22:35
Как это "идут через центр"? В принципе GView любит центровать изображение и расширять холст автоматически, мб в этом проблема?


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 13, 2014, 22:54
Может быть и в этом, только это делает компонент практически непригодным. Обычный график, например выручки магазина: по горизонтальной оси даты, по вертикальной выручки - получается ломаная линия. Нафига мне "оптический прицел" с крестиком посередине?


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 14, 2014, 09:09
C этим разобрался - там в настройках центровка отключается.

Ещё вопрос. Вся графика рисуется в одном обработчике нажатия кнопки:

Код
C++ (Qt)
void Widget::MyEventHandler1()
{
   QGraphicsScene *scene = new QGraphicsScene(ui->graphicsView);
 
   QPen pen1(Qt::green);//Просто выбираем цвет для карандашика
 
   scene->addLine(0,90,180,90,pen1);
   scene->addLine(90,0,90,180,pen1);
 
   QPen pen2(Qt::red);
 
   scene->addLine(0, 0, 30, 30, pen2);
   scene->addLine(30, 30, 100, 60, pen2);
   scene->addLine(100, 60, 140, 10, pen2);
 
   ui->graphicsView->setScene(scene);
}

Как сделать, чтобы нажатия разных кнопок рисовали в одну и ту же scene, как сделать её одной для всех кнопок? Пробовал объявить её глобальной - прога рушится при запуске.

Или нужно для каждой кнопки создавать свою сцену, и мутить с копированием того, что было нарисовано ранее?


Название: Re: Рисование на форме.
Отправлено: Bepec от Июля 14, 2014, 10:55
Так сделайте её полем класса. Зачем динамически создавать?
И да, рушиться не должно, у вас что то не так в коде :)


Название: Re: Рисование на форме.
Отправлено: Igors от Июля 14, 2014, 11:14
Обычный график, например выручки магазина: по горизонтальной оси даты, по вертикальной выручки - получается ломаная линия.
Тогда последующий выбор QGraphicsScene ничем не обоснован. Задач типа "выбрать/передвинуть отрезок" нет - так зачем делать отрезок примитивом? График предназначен "просто для созерцания" - ну и рисуйте его в paintEvent. Заведите простую структуру, напр
Код
C++ (Qt)
struct MyGraf : public QList <QPoint> {
QColor mColor;
};
Рисование - простой цикл, добавлять точки без проблем


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 14, 2014, 14:14
Так сделайте её полем класса. Зачем динамически создавать?
И да, рушиться не должно, у вас что то не так в коде :)

Тут проблема в том, что при динамическом создании ей в качестве параметра ui->graphicsView передаётся. Вот как раз пробовал сделать её глобальной без этого параметра:

Код
C
QGraphicsScene *scene = new QGraphicsScene();

так компилируется, но при запуске программы рушится, до нажатия любых кнопок. Как её правильно сделать полем класса?



Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 14, 2014, 14:34
Тогда последующий выбор QGraphicsScene ничем не обоснован. Задач типа "выбрать/передвинуть отрезок" нет - так зачем делать отрезок примитивом? График предназначен "просто для созерцания" - ну и рисуйте его в paintEvent. Заведите простую структуру, напр

Я выбрал graphicsView в компонентах, т.к. думал, что это специальный компонент для вывода графики, ну и в т.ч. для рисования в нём. А в сети нашёл пример, как им практически пользоваться (с использованием QGraphicsScene). Может на нём как по другому рисовать можно, я это пока не знаю.

В принципе то я разобрался. Например

Код
C++ (Qt)
   scene->addLine(0, 0, 40, 120, pen2);
   scene->addLine(40, 120, 100, 60, pen2);

выдаст таки ломаную линию, начинающуюся из верхнего левого угла компонента (0,0), что ожидаемо. Но если убрать (закомментировать) первую линию, то вторая почему-то начинает начинаться с 0,0, что уже сюрприз. Но если первой вывести чёрточку, начинающуюся с нуля, хоть scene->addLine(0,0,0,1,pen1);, то остальные линии начинают "попадать" в координаты. Костыль?



Название: Re: Рисование на форме.
Отправлено: alex312 от Июля 14, 2014, 15:06
Alexu007, а вы принципиально хотите разработать свой класс для отображения графиков, или вам подойдут готовые решения ?


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 14, 2014, 15:44
Alexu007, а вы принципиально хотите разработать свой класс для отображения графиков, или вам подойдут готовые решения ?
Я ничего не разрабатываю - я просто хочу освоить примитивнейшую графику, а именно - рисование на форме. Это даже не по работе или учёбе - это для себя. Готовые конечно подойдут. Я и нашёл готовое решение с QGraphicsScene(ui->graphicsView) - ссылку я в начале темы давал. Но товарищ, предложивший это решение, нарисовал посередине крестик (координатная сетка) и чёрточку - посчитал на этом свою задачу выполненной. А при попытке прикрутить это решение к своим нуждам начались проблемы.

Я понимаю, что ломаную линию (график) проще в paintEvent нарисовать, передав туда массив с координатами. Следующей я хочу нарисовать уже синусоиду, там координат поболее будет, но можно, например, с помощью QByteArray передать. Просто вопрос - graphicsView разве не специально для этого придуман?

Да, и ещё, память о билдере с толку сбивает. Там то же самое без всякого гимора реализуется: просто рисуешь на канве, и канва сама твой рисунок помнит и перерисовывает где надо. Уж куда проще...


Название: Re: Рисование на форме.
Отправлено: Bepec от Июля 14, 2014, 15:48
Alexu007- GraphicsView это довольно сложный компонент для решения довольно сложных проблем связанных с 2D рисованием/перемещением и управлением объектами.

Если вам нужно просто график построить - проще или взять Qwt как готовое решение (хотя сам в нём не разобрался я :) ) или же по совету профессионалов рисовать просто на виджете самому.

PS рисование на форме - paintEvent. Графики - Qwt. Фигня типо 2D моделирования и/или игр - GraphicsView.


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 14, 2014, 15:53
Вот 2D рисование с толку и сбивает - а я чем занимаюсь? И кстати, если надо совсем просто, без массивов и тп - GraphicsView все ж таки подходит:


Название: Re: Рисование на форме.
Отправлено: Igors от Июля 14, 2014, 16:31
Я понимаю, что ломаную линию (график) проще в paintEvent нарисовать, передав туда массив с координатами. Следующей я хочу нарисовать уже синусоиду, там координат поболее будет, но можно, например, с помощью QByteArray передать. Просто вопрос - graphicsView разве не специально для этого придуман?
Нет, graphicsView предназначен для интерактивной работы с нарисованным. В контейнерах обычно хранят то что сами задают. Напр (40, 120)(100, 60) - никто не знает откуда это взялось - сами и храните. А для синусоиды достаточно хранить амплитуду, фазу и время (размер по оси X).

Вот 2D рисование с толку и сбивает - а я чем занимаюсь? И кстати, если надо совсем просто, без массивов и тп - GraphicsView все ж таки подходит:
Появляется человек и начинает задавать, ну скажем, "наивные" вопросы. Ничего страшного, нормально. Однако проходит ощутимое время - не месяц-другой, а гораздо больше. Но вопросы остаются столь же "наивными". Что это? Печать (де)билдера на всю жизнь?  :)


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 14, 2014, 18:11
Типо ага. Нужна книга "Qt для носорога". А пока нет такой - приходится мозги напрягать. Некоторые вещи в Qt весьма неочевидны.


Название: Re: Рисование на форме.
Отправлено: Bepec от Июля 14, 2014, 18:55
По сравнению с остальными библиотеками, она превосходно документирована. Нужно лишь читать.


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 17, 2014, 12:48
Такой вопросик... В QByteArray только byte записывать можно, а нет ли чего-нибудь похожего для int?


Название: Re: Рисование на форме.
Отправлено: carrygun от Июля 18, 2014, 04:34
Такой вопросик... В QByteArray только byte записывать можно, а нет ли чего-нибудь похожего для int?
Насколько похожего? Можно, например, QList<int> использовать.


Название: Re: Рисование на форме.
Отправлено: Alexu007 от Июля 18, 2014, 21:36
Насколько похожего?
Ну во первых это динамический массив, я загоняю туда сколько надо инфы (в разумных пределах, конечно) и не парюсь о выходе за пределы массива. В случае с int нужно либо обычный массив (и париться о выходе за пределы массива), либо мутить тему со связанными списками.
Во вторых - сервис: .size .clear и прочие мелкие радости жизни. Удобно. Не надо засорять программу "лишним" кодом и тратить время на написание этого кода.

P.S. QList<int>  вместо QByteArray подошёл, даже в коде ничего менять не пришлось. Спасибо.