Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: niktagor от Май 15, 2010, 15:46



Название: QPainter для совсем новичков
Отправлено: niktagor от Май 15, 2010, 15:46
 Здравствуйте. Заранее большое спасибо всем, кто откликнется. Пытаюсь разобраться, как рисовать на виджетах с помощью QPainter. После прочтения документации, мой мозг сгенерировал вот такой код:
Код:
#include <QtGui>
#include <QPainter>
int main(int argc, char **argv) {

    QApplication app(argc,argv);
    QWidget wgt;
    wgt.resize(500,500);

    QPainter painter;
    painter.begin(&wgt);
    painter.setPen(QPen(Qt::black,3));
    painter.drawLine(QPointF(5,5),QPointF(100,100));
    painter.end();

    wgt.show();

    return app.exec();
}

Окошко запускается, а линия не рисуется. В чем причина?
Вот такая штука на отладке:

Запускается D:\programs\2\debug\2.exe...
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active
QPainter::end: Painter not active, aborted
D:\programs\2\debug\2.exe завершился с кодом 0

Из пока не получилось вырвать работающий кусок кода. Нашел вот тут (http://hghltd.yandex.net/yandbtm?qtree=LzLTYyVXkpOq%2Fl1io6J0JvBxizVyiOw5re0KzGtU9CP9h6cTx%2FBG1eBRKPM8UtzzS4%2BMhk%2BzG84tONPCF9w6GSW9GqqFlKAFUwNQQt70sBXXjQKOV20Bz55%2F%2FYP9KSOMj3BDX3HGpizW3ycjswD9ZUXZliE%2BSTI9sSWVcDG14eSY0FnpjZ8DXqvwemyjmCKroi%2F8cNr27SKeWH%2FkGb%2BXliUhUrD3gSC8Is0w%2FePlWnRwzbxIgzi3t75ghAu2GVftZwcuw2gxd0AQe87POOAAzcBjR6qZJDdrGNernXY5%2F4vTWNYwEuk7qJ1xWNrpNJDSmnMperjY3z3TsxOp%2B%2BL9u%2FKwAnDKM1X2cTxgKdt%2F8BKJhDso6K1P%2FiijT86awkmkVaavdXWCfn7hypRg25azvsQ84EN820dRfSoS46grhQiu13W7oULUJYG8b297uoxp82gS6Hx9rGtdpwS4IWV1jqjSTt%2FQyJoguirrZ3cfeRHCB7fomHnPyCob8XMwtnj5jZ88lmg9CsNgWxlc9eYlVxJKtZnd4qNaAfFsV84pZe0%3D&text=%EF%EE%EC%EE%E3%E8%F2%E5%20Qpainter&url=http%3A%2F%2FLinuxForum.ru%2Findex.php%3Fshowtopic%3D16171) такое сообщение:
Цитировать
Вот тебе минималистический пример виджета, на котором можно что-нибудь рисовать:
Код
Код:
class PaintWidget : public QWidget
{
    Q_OBJECT

    public:
        PaintWidget(QWidget *parent = 0);
        void draw( QPainter  *painter);
    protected:
        void paintEvent(QPaintEvent *event);
};
PaintWidget::PaintWidget(QWidget *parent)
    : QWidget(parent)
{
    setPalette(QPalette(QColor(250, 250, 200)));
    setAutoFillBackground(true);
}

void PaintWidget::paintEvent(QPaintEvent * /* event */)
{
     QPainter  painter(this);
    draw(&painter);
}

void PaintWidget::draw( QPainter  *painter)
{
    painter->setRenderHint( QPainter ::Antialiasing, true);
    painter->drawLine(0, 0, 20, 30);
}

Но у меня не получается его вставить в свой проект. Сборщик аж 4 раза ругается вот так:
undefined reference to `vtable for PaintWidget'
на строчке
Код:
: QWidget(parent)


Если кто-нибудь напишет минималистичный код, в котором все работает и выводит на экран какие-нибудь точки или линии, буду очень благодарен. Или подскажите, как мне с этим всем добром разобраться.


Название: Re: QPainter для совсем новичков
Отправлено: alexman от Май 15, 2010, 16:14
http://doc.qt.nokia.com/4.6/painting-basicdrawing.html


Название: Re: QPainter для совсем новичков
Отправлено: jack_r от Май 15, 2010, 16:54
Но у меня не получается его вставить в свой проект. Сборщик аж 4 раза ругается вот так:
undefined reference to `vtable for PaintWidget'
Пример этого кода нужно поместить в отдельный класс с заголовком и исходником paintwidget.h и paintwidget.cpp, а затем включить заголовок в main.cpp.


Название: Re: QPainter для совсем новичков
Отправлено: lit-uriy от Май 15, 2010, 20:10
>>Окошко запускается, а линия не рисуется. В чем причина?
В документации сказано, что рисовать на виджете, можно только из его обработчика события рисования, т.е.
MyWidget::paintEvent(...)
Иные способы рисования на виджете не для новичка


Название: Re: QPainter для совсем новичков
Отправлено: niktagor от Май 15, 2010, 22:59
Но у меня не получается его вставить в свой проект. Сборщик аж 4 раза ругается вот так:
undefined reference to `vtable for PaintWidget'
Пример этого кода нужно поместить в отдельный класс с заголовком и исходником paintwidget.h и paintwidget.cpp, а затем включить заголовок в main.cpp.


А можете объяснить, что из этого текста куда записать, и что нужно в main написать, чтобы он нарисовал мне что-нибудь?


Название: Re: QPainter для совсем новичков
Отправлено: alexman от Май 16, 2010, 10:08
Написали же, что нужно void QWidget::paintEvent ( QPaintEvent * event ) переопределять.


Название: Re: QPainter для совсем новичков
Отправлено: marbius от Май 16, 2010, 10:52
Вот Вам, в принципе, минимум, чтобы начать самостоятельно рисовать.

Код:
#include <QtGui>

class myWidget : public QWidget
{
    public:
        myWidget (QWidget *parent=0) : QWidget(parent)
        {
        }

        void paintEvent(QPaintEvent *pe)
        {    QPainter p(this);
             // тут и только тут должны быть все Ваши "рисования"
             p.drawLine(0,0,100,100);
        }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    myWidget w;
    w.show();
    return a.exec();
}



Название: Re: QPainter для совсем новичков
Отправлено: niktagor от Май 16, 2010, 12:51
 Большое спасибо! Работает. Позже я разберусь, что все это значит, а пока на более простых вещах потренируюсь. Нигде я не смог такого хорошего примера найти.


Название: Re: QPainter для совсем новичков
Отправлено: niktagor от Май 16, 2010, 16:10
 А если я хочу, например, чтобы на виджете рисовалось не при его создании, а при нажатии кнопочки, что нужно сделать? Нужно paintEvent поключить к сигналу кнопки в качестве слота, а внутри него уже проверять, был ли это сигнал кнопки или другое неподходящее событие? Или попроще можно?


Название: Re: QPainter для совсем новичков
Отправлено: jack_r от Май 16, 2010, 16:12
Но у меня не получается его вставить в свой проект. Сборщик аж 4 раза ругается вот так:
undefined reference to `vtable for PaintWidget'
Пример этого кода нужно поместить в отдельный класс с заголовком и исходником paintwidget.h и paintwidget.cpp, а затем включить заголовок в main.cpp.


А можете объяснить, что из этого текста куда записать, и что нужно в main написать, чтобы он нарисовал мне что-нибудь?

paintwidget.h - заголовочный файл
Код:
#include <QWidget>

class PaintWidget : public QWidget
{
    Q_OBJECT

    public:
        PaintWidget(QWidget *parent = 0);
        void draw( QPainter  *painter);
    protected:
        void paintEvent(QPaintEvent *event);
};

paintwidget.cpp - исходный код
Код:
#include <QPainter>

#include "paintwidget.h"

PaintWidget::PaintWidget(QWidget *parent)
    : QWidget(parent)
{
    setPalette(QPalette(QColor(250, 250, 200)));
    setAutoFillBackground(true);
}

void PaintWidget::paintEvent(QPaintEvent * /* event */)
{
     QPainter  painter(this);
    draw(&painter);
}

void PaintWidget::draw( QPainter  *painter)
{
    painter->setRenderHint( QPainter ::Antialiasing, true);
    painter->drawLine(0, 0, 20, 30);
}

main.cpp - исходный код
Код:
#include <QtGui>

#include "paintwidget.h"

int main(int argc, char **argv) {

    QApplication app(argc,argv);
    PaintWidget wgt;
    wgt.resize(500,500);
    wgt.show();

    return app.exec();
}


Название: Re: QPainter для совсем новичков
Отправлено: jack_r от Май 16, 2010, 16:22
А если я хочу, например, чтобы на виджете рисовалось не при его создании, а при нажатии кнопочки, что нужно сделать? Нужно paintEvent поключить к сигналу кнопки в качестве слота, а внутри него уже проверять, был ли это сигнал кнопки или другое неподходящее событие? Или попроще можно?
Да, примерно так.
Если более подробно, то в paintEvent() в зависимости от состояния флага рисовать что-либо. А флаг изменять в слоте вызываемом при клике на кнопку.
Код:
void MyWidget::paintEvent(QPaintEvent *e)
{
  Q_UNUSED(e);

  QPainter  painter(this);
  if (mPaintRect)
  {
    // рисуем прямоугольник
    painter.drawRect(0, 0, 10, 10);
  }
}

void MyWidget::doPaintRect() // слот
{
  mPaintRect = !mPaintRect;
  update(); // вызывает paintEvent
}

Ещё нужно инициализировать флаг в конструкторе.


Название: Re: QPainter для совсем новичков
Отправлено: lit-uriy от Май 16, 2010, 19:05
>>ужно paintEvent поключить к сигналу кнопки в качестве слота
paintEvent - не слот, следовательно, как слот использовать нельзя


Название: Re: QPainter для совсем новичков
Отправлено: niktagor от Май 18, 2010, 10:42
Большое спасибо всем, кто ответил!! Потихоньку начинаю понимать, что к чему.