[SOLVED]При перерисовке виджета старый рисунок остаётся



  • Добрый день, помогите пожалуйста.
    Есть два класса, Line и Triangle
    В Line в функцию draw() передаётся указатель на QPainter и происходит отрисовка
    @
    Line::Line(QWidget *parent, Point *pt1, Point *pt2) : QWidget(parent), point1(pt1), point2(pt2)
    {
    setMinimumSize(parent->size());
    }
    void Line::draw(QPainter *painter)
    {
    painter->setPen(QPen(Qt::red, 1, Qt::SolidLine));
    qreal x1 = point1->getX(), y1 = point1->getY(),
    x2 = point2->getX(), y2 = point2->getY();
    qreal k, b, y;
    k = (y2 - y1) / ( x2 - x1 );
    b = y1 - k * x1;
    if(x1 > x2) {
    int t = x1; x1 = x2; x2 = t;
    }
    if (x1 != x2)
    {
    for(double x = x1; x < x2; x += 0.1)
    {
    y = k * x + b;
    painter->drawPoint(QPointF(x, y));
    }
    }
    else
    {
    if (y1 > y2) {
    int ty = y1; y1 = y2; y2 = ty;
    }
    for(qreal y = y1; y < y2; y++)
    painter->drawPoint(QPointF(x1, y));
    }
    }
    @
    В классе Triangle переопределен paintEvent. Там создаются три объекта Line (объявлены в private) и происходит их отрисовка
    @
    void Triangle::paintEvent(QPaintEvent *)
    {
    ln1 = new Line(this, A, B);
    ln2 = new Line(this, A, C);
    ln3 = new Line(this, B, C);
    QPainter painter(this);
    ln1->draw(&painter);
    ln2->draw(&painter);
    ln3->draw(&painter);
    }
    @
    В MainWindow создаётся объект Triangle (объявление в private), в качестве родителя передаётся прямоугольный виджет, созданный в дизайнере.
    @
    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    trgl = new Triangle(ui->graphicArea, 50, 50, 50);
    ui->graphicArea->setAttribute(Qt::WA_OpaquePaintEvent);
    ui->graphicArea->show();
    @
    Проблема вот в чем: есть кнопка, при нажатии на которую треугольник должен перерисоватся с заданными координатами, но вместо перерисовки рисуется новый треугольник, старый остаётся на месте (пробовал не использовать new, а менять координаты через сэттер, не помогло).
    @
    void MainWindow::setTriangleButton()
    {
    qreal x, y, len;
    x = ui->TriangleXCoord->value();
    y = ui->TriangleYCoord->value();
    len = ui->TriangleLength->value();
    trgl = new Triangle(ui->graphicArea, x, y, len);
    trgl->show();
    }
    @
    Почему так?
    Заливать фон полностью перед пересозданием объекта не выйдет, у меня там не только треугольник.
    Буду очень благодарен за помощь!



  • Попробуйте удалять линию перед тем как её рисовать.
    Сохраняйте текущие координаты линии как члены класса Line и сделайте метод clear() в котором линия рисуется цветом фона.
    После этого рисуйте линию по новым координатам.

    В текущей имплементации функции void Triangle::paintEvent(QPaintEvent *) течёт память.
    Если будете удалять по старым координатам и рисовать по новым то лучше выделить память под Line в конструкторе Triangle и удалять в деструкторе.



  • [quote author="andreyc" date="1402793558"]Попробуйте удалять линию перед тем как её рисовать.
    [/quote]
    Имеете в виду delete ln1; delete ln2; delete ln3; в начале void Triangle::paintEvent(QPaintEvent *) ? Не помогло.
    [quote author="andreyc" date="1402793558"]
    Сохраняйте текущие координаты линии как члены класса Line и сделайте метод clear() в котором линия рисуется цветом фона.
    После этого рисуйте линию по новым координатам.
    [/quote]
    Это вариант, но у меня может быть несколько фигур, которые могут пересекаться. В таком случае в местах пересечений будут пустые места. По возможности хотелось бы избежать такого.
    [quote author="andreyc" date="1402793558"]
    В текущей имплементации функции void Triangle::paintEvent(QPaintEvent *) течёт память.
    [/quote]
    А в каком месте, подскажите пожалуйста.



  • [quote]Имеете в виду delete ln1; delete ln2; delete ln3; в начале void Triangle::paintEvent(QPaintEvent *) ? Не помогло.[/quote]
    нет, нет. я имел ввиду, как раз рисовать фоновым цветом линию по старым координатам.

    [quote]Это вариант, но у меня может быть несколько фигур, которые могут пересекаться. В таком случае в местах пересечений будут пустые места. По возможности хотелось бы избежать такого.[/quote]
    я думаю, что в такой ситуации вы должны перерисовывать все фигуры которые попадают в "QPaintEvent::rect()":http://qt-project.org/doc/qt-5/qpaintevent.html#rect

    [quote]
    А в каком месте, подскажите пожалуйста.
    [/quote]
    если вы нигде не удаляете ln1, ln2, ln3 после painEvent(), то вы каждый раз переписываете указатели на вызове paintEvent() и то что на что они указывали до этого остаётся не удалёным.
    @
    ln1 = new Line(this, A, B);
    ln2 = new Line(this, A, C);
    ln3 = new Line(this, B, C);
    @



  • [quote]
    если вы нигде не удаляете ln1, ln2, ln3 после painEvent(), то вы каждый раз переписываете указатели на вызове paintEvent() и то что на что они указывали до этого остаётся не удалёным.
    [/quote]
    Если заменить переписывание указателей вызовом сэттеров, утечка памяти пропадет?
    @
    ln1->setPoints(A, B);
    ln2->setPoints(A, C);
    ln3->setPoints(B, C);
    @



  • [quote]Если заменить переписывание указателей вызовом сэттеров, утечка памяти пропадет?[/quote]
    да если память под ln1, ln2, ln3 будет выделена заблаговременно, например в конструкторе Triangle и потом удалена в деструкторе.



  • [quote author="andreyc" date="1402798378"]
    нет, нет. я имел ввиду, как раз рисовать фоновым цветом линию по старым координатам.
    [/quote]
    Сделал в классе triangle метод clear(), вызываю перед основной отрисовкой.
    @
    void Triangle::clear(QPainter *painter)
    {
    ln1->setPoints(A_old, B_old);
    ln2->setPoints(A_old, C_old);
    ln3->setPoints(B_old, C_old);
    painter->setPen(QPen(Qt::black, 1, Qt::SolidLine));
    ln1->draw(painter);
    ln2->draw(painter);
    ln3->draw(painter);
    }
    @
    Старые координаты получаю при вызове сэттера, при вызове конструктора выделяю под них память.
    Теперь все работает, большое спасибо за помощь!



  • Спасибо за предоставленую возможность помочь.
    Добавьте пожалуйста [SOLVED] к заголовку начального сообщения.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.