QT: repaint() не перерисовывает виджет

114
27 ноября 2020, 12:30

По ТЗ необходимо реализовать построчную закраску многоугольника в двух вариантах - с задержкой после отрисовки каждой линии и без нее.
Есть класс LineFillerView, наследний QGraphicsView. Решил использовать repaint() - написано, чтоон перерисвывает объект немедленно, ног ничего не происходит, и после нескольких секунд программа закрашивает все разом. Вот как это выглядит (вариант с отрисовкой после обработки каждого ребра многоугольника):

void LineFillerView::fill_polygon_barrier(const List<Edge> &edges, const QColor &filler_color, const QColor &bg_color, bool delay)
{
    if (edges.size() > 2)
    {
        QRectF polygon_rect = get_polygon_rect(edges);
        const double barrier_x = polygon_rect.x() + polygon_rect.width() / 2;
        ConstListIterator<Edge> end = edges.cend();
        ++end;
        for (ConstListIterator<Edge> runner = edges.cbegin(); runner != end; ++runner)
        {
            invert(scene(), *runner, barrier_x, filler_color, bg_color, delay); // Инвертирует все пиксели, которые нужно инвертировать для данной грани
            repaint();
        }
    }
}

В результате многоугольник отрисвывается сразу, и я не понимаю, почему
P.S. paintEvent не переопределял
Удалось это реализовать только с qWait, но это костыль, причем в моем случае он мешает - если во время "медленной" закраски нажать "сброс сцены", сцена очистится, но закраска продолжит рисоваться уже на очищенной сцене.

Отрисовка многоугольника:

void LineFillerView::new_point(const Point &to)
{
    if (!attributes.first_is_set)
    {
        IntPoint *point = new IntPoint(my_round(to.x), my_round(to.y), attributes.edges_color);
        scene()->addItem(point);
        attributes.add_point(to);
    }
    else if (to != attributes.last_point())
    {
        Point from = attributes.last_point();
        scene()->addLine(from.x, from.y, to.x, to.y, QPen(attributes.edges_color));
        attributes.add_point(to);
    }
}
void LineFillerView::close_polygon()
{
    if (attributes.polygon_is_obtainable())
    {
        Point from = attributes.last_point();
        scene()->addLine(from.x, from.y, attributes.first.x, attributes.first.y, QPen(attributes.edges_color));
        attributes.add_point(attributes.first);
        attributes.first_is_set = false;
    }
}
void LineFillerView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        new_point(Point(event->x(), event->y()));
    else if (event->button() == Qt::RightButton)
        close_polygon();
}

Дополнение пикслелей:

void invert(QGraphicsScene *scene, const Edge &edge, const double barrier_x, const QColor &filler_color, const QColor &bg_color, bool delay)
{
    int x1, x2, y1, y2;
    if (edge.from.y < edge.to.y)
    {
        x1 = edge.from.x;
        x2 = edge.to.x;
        y1 = edge.from.y;
        y2 = edge.to.y;
    }
    else
    {
        x1 = edge.to.x;
        x2 = edge.from.x;
        y1 = edge.to.y;
        y2 = edge.from.y;
    }
    double l = double(x2 - x1) / (y2 - y1);
    QImage image(scene->width(), scene->height(), QImage::Format_ARGB32);
    QPainter painter(&image);
    //painter.setRenderHint(QPainter::Antialiasing);
    scene->render(&painter);
    int y = y1;
    if (delay)
        while (y < y2)
        {
            int xl, xr;
            set_x_limits(xl, xr, x1 + (y - y1) * l, barrier_x);
            invert_line(scene, image, xl, xr, y, bg_color, filler_color);
            qApp->processEvents();
            ++y;
        }
    else
        while (y < y2)
        {
            int xl, xr;
            set_x_limits(xl, xr, x1 + (y - y1) * l, barrier_x);
            invert_line(scene, image, xl, xr, y, bg_color, filler_color);
            ++y;
        }
}
void invert_line(QGraphicsScene *scene, const QImage &image, int x, const int xe, const int y, const QColor &bg_color, const QColor &filler_color)
{
    while (x < xe)
    {
        QColor color = (QColor(image.pixel(x, y)) == bg_color? filler_color : bg_color);
        IntPoint *point = new IntPoint(x, y, color);
        scene->addItem(point);
        ++x;
    }
}

На всякий случай, ссылка на весь проект

READ ALSO
Вынести функцию в отдельный поток

Вынести функцию в отдельный поток

есть программа, как в аргументы функции передать целый класс, и его изменять так, что-бы именения были видны в main()?

120
В чём разница между decltype(auto) и auto&amp;&amp;?

В чём разница между decltype(auto) и auto&&?

В чём разница между decltype(auto) и auto&&?

99
константное значение n, m

константное значение n, m

Пытаюсь получить транспонированную матрицу, но выдает ошибку Выражение должно иметь константное значение n, m; Не могу понять что не так, пример...

143
Python extension modules без линковки к pythonXX.dll

Python extension modules без линковки к pythonXX.dll

Возможно ли использовать импортируемые dll (имеющие расширениеpyd) в питоне на Windows без линковки к pythonXX

94