crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> рисование на QWidget
voipp
  опции профиля:
сообщение 20.10.2009, 22:44
Сообщение #1


Участник
**

Группа: Участник
Сообщений: 116
Регистрация: 20.10.2009
Из: Msk
Пользователь №: 1166

Спасибо сказали: 0 раз(а)




Репутация:   0  


всем добрый вечер!

у меня такой вопрос, но сначала код
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();


    return a.exec();
}

class PAINT : public QWidget
{
//......
}
//.....
определение функции класса PAINT :
void PAINT::paintEvent(QPaintEvent*){
    QPointF center(this->width()/2.0, this->height()/2.0);
    QPointF ptr1(center.x()+ 10,center.y());

    for(float fi= (Pi/4.0); fi<= (2.0*Pi); fi+= (Pi/4.0)){
        QPointF ptr2(center.x()+ cos(fi)*10, center.y()+ sin(fi)*10);
        line(ptr1,ptr2);
        line(center,ptr2);
        //delete &ptr1;
        QPointF ptr1= ptr2;
        //delete &ptr2;
    };
};


я прочитал что для рисования вызывается событие перерисовка(paintEvent).Вопрос 1 - в каком месте программы вызывается painEvent(я так понимаю что это либо в main.cpp либо в widget.h) и 2 - все нормально работает если перегрузить функцию paintEvent в конструкторе widget но как быть если я хочу paintEvent поместить не в этот конструктор а в другой класс?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 20.10.2009, 23:17
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(voipp @ 21.10.2009, 2:44) *
Вопрос 1 - в каком месте программы вызывается painEvent(я так понимаю что это либо в main.cpp либо в widget.h)
функция a.exec(); обрабатывает события которые пришли от ОСьки. Вызов paintEvent происходит в момент обработки событий, и это происходит регулярно, когда ось сообщает приложению, что его мордочка требует перерисовки.

Цитата(voipp @ 21.10.2009, 2:44) *
2 - все нормально работает если перегрузить функцию paintEvent в конструкторе widget
в конструкторе ты ничего не перегружаешь! конструктор - функция, которая вызывается при создании объекта для установки начальных свойств (данных) если они необходимы.
Перегрузка - это создание одноимённой функции к уже существующей, но с иными аргументами

посмотри внимательно на функцию main:
int main(int argc, char *argv[])
{
    QApplication a(argc, argv); // Вызывается конструктор класса QApplication и создаётся объект (экземпляр) этого класса

    Widget w; // Вызывается конструктор класса Widget и создаётся объект (экземпляр) этого класса
    w.show(); // вызывается метод show класса Widget, который говорит виджету, что его надо показывать (рисовать)

    return a.exec(); // этот метод содержит бесконечный цикл обработки событий, здесь программа сидит всегда!
}
Первым придёт событие перерисовки, т.к. виджет верхнего уровня один, то только для него приложение вызовет Widget::paintEvent, затем управление вернётся в цикл обработки событий (внутри QApplication::exec), всякий раз когда, с окном что-то происходит, например, над ним двигается мышь, ОСька шлёт событие приложению. Т.к. все процессы в системе выполняются последовательно, то ОСь их просто записывает в очередь. А когда дело доходит до приложения оно из этой очереди извлекает события и вызывает соответствующие методы наследников класса QWidget. Всё это происходит (в рамках приложения) в нутри QApplication::exec

Цитата(voipp @ 21.10.2009, 2:44) *
но как быть если я хочу paintEvent поместить не в этот конструктор а в другой класс?
Я на 100% уверен, что реальная необходимость в этом нужна редко.
В Qt используется компонентный подход к программированию. Компоненты между собой взаимодействуют посредством сигналов и слотов.

Можно создать виджет со специфическими слотами, и сигналить ему, чтобы он что-то эдакое нарисовал на себе.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
voipp
  опции профиля:
сообщение 21.10.2009, 1:10
Сообщение #3


Участник
**

Группа: Участник
Сообщений: 116
Регистрация: 20.10.2009
Из: Msk
Пользователь №: 1166

Спасибо сказали: 0 раз(а)




Репутация:   0  


конструктор я имел ввиду класса PAINT а перегружал я paintEvent. Спасибо большое за дополнительные сведения по Qt !
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
voipp
  опции профиля:
сообщение 23.10.2009, 17:37
Сообщение #4


Участник
**

Группа: Участник
Сообщений: 116
Регистрация: 20.10.2009
Из: Msk
Пользователь №: 1166

Спасибо сказали: 0 раз(а)




Репутация:   0  


Я создал обычную функцию рисующую линию и в конструкторе класса mainwindow ее вызываю - но она ничего не рисует(вызов конструктора происходит до application.exec() )
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 23.10.2009, 17:56
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(voipp @ 23.10.2009, 18:37) *
Я создал обычную функцию рисующую линию и в конструкторе класса mainwindow ее вызываю - но она ничего не рисует(вызов конструктора происходит до application.exec() )

И не нарисует. Все рисование на виджет должно выполняться из paintEvent().
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
vanvo
  опции профиля:
сообщение 23.10.2009, 20:55
Сообщение #6


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 18.8.2008
Пользователь №: 267

Спасибо сказали: 0 раз(а)




Репутация:   0  


Тоже недавно стал разбираться с 2D рисованием. Вопрос: как организовать отрисовку на widget'е, только после нажатия кнопки? И при каждом нажатии кнопки происходила перерисовка виджета.

Сообщение отредактировал vanvo - 23.10.2009, 20:57
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 23.10.2009, 21:14
Сообщение #7


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(vanvo @ 24.10.2009, 0:55) *
как организовать отрисовку на widget'е, только после нажатия кнопки? И при каждом нажатии кнопки происходила перерисовка виджета.
Цитата(Litkevich Yuriy @ 21.10.2009, 3:17) *
Можно создать виджет со специфическими слотами, и сигналить ему, чтобы он что-то эдакое нарисовал на себе.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
vanvo
  опции профиля:
сообщение 23.10.2009, 21:18
Сообщение #8


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 18.8.2008
Пользователь №: 267

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Litkevich Yuriy @ 23.10.2009, 22:14) *
Можно создать виджет со специфическими слотами, и сигналить ему, чтобы он что-то эдакое нарисовал на себе

А можно поподробней? Ставит в тупик:
Цитата(BRE @ 23.10.2009, 18:56) *
Все рисование на виджет должно выполняться из paintEvent().

Т.е. в слоте нужно создавать событие?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 23.10.2009, 21:29
Сообщение #9


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Т.е. Идея:
Есть главный виджет (форма), на ней другие виджеты (контролы). Один из них называется Холст (Canvas). Из главного виджета рисуем на Холсте, т.е. весь код рисования сосредоточен в одной из функций главного виджета.
Если со временем, нужно изменить программу мы переписываем этот самый код (т.е. главного виджета).
Так было в Qt3, так есть у многих других библиотек.

Идея Qt4:
Нет Холста (такого класса), всякий виджет - холст.
Создаём наследника QWidget - это будет замена Холста из первой идеи, весь код рисования помещаем в этот виджет (в отдельную функцию).
Из PaintEvent вызываем эту функцию. Ну а функцию реализуем так как удобно. Далее можно пойти двумя дорогами:
- 1 -
Создать слот принимающий указатели на уже подготовленные массивы данных (X и Y) для рисования. Соответственно нужно завести в классе два локальных указателя, а в этом слоте лишь копировать аргументы слота в локальные переменные. В функции PaintEvent рисовать данные по получаемые по локальным указателям (если они не нулевые).
- 2 -
В Qt есть класс QImage (не виджет), на котором можно рисовать, где угодно и когда угодно. Хоть в другом потоке (виджеты не могут находится в других потоках, кроме основного). В классе нашего "холста" делаем слот принимающий ссылку на QImage, рисуем где хотим на QImage и передаём его через слот в наш "холст". Ну а в функции PaintEvent будем рисовать содержимое QImage.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
vanvo
  опции профиля:
сообщение 23.10.2009, 22:43
Сообщение #10


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 18.8.2008
Пользователь №: 267

Спасибо сказали: 0 раз(а)




Репутация:   0  


Litkevich Yuriy, решил попробовать 1 дорогой. Для примера рисую эллипс, координаты которого передаю во внешнюю функцию класса.
Вот сам класс:
class Histogram : public QWidget {
protected:
    virtual void paintEvent(QPaintEvent *event)
    {
                  p = new QPainter(this);
      p->setPen(QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap));
      p->setBrush(QBrush(Qt::black, Qt::SolidPattern));
      p->drawEllipse(0, 0, x, y);
      p->end();
   }
private:
      QPainter *p;
      int x,y;
public:
    Histogram(QWidget* pwgt = 0)
{
    x = 20;
    y = 30;
  }
    void updateHistogram(int xValue, int yValue)
{
   x = xValue;
   y = yValue;
}  
};

Вызываю updateHistogram из слота, обрабатывающего нажатие на кнопку в виде:
widget_2->updateHistogram(100,100);

В этом случае нажатие на кнопку не приводит к изменению эллипса, но при изменении размера окна эллипс "перескакивает" на новые координаты.
Пробовал создать искусственное событие ресайза в updateHistogram в виде:
QEvent *event = new QEvent(QEvent::Resize);
QApplication::sendEvent(this, event);

Но это ничего не изменило. Прошу подсказать что исправить.

Сообщение отредактировал vanvo - 23.10.2009, 22:47
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 23.4.2024, 23:14