По ТЗ необходимо реализовать построчную закраску многоугольника в двух вариантах - с задержкой после отрисовки каждой линии и без нее.
Есть класс 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;
}
}
На всякий случай, ссылка на весь проект
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
есть программа, как в аргументы функции передать целый класс, и его изменять так, что-бы именения были видны в main()?
Пытаюсь получить транспонированную матрицу, но выдает ошибку Выражение должно иметь константное значение n, m; Не могу понять что не так, пример...
Возможно ли использовать импортируемые dll (имеющие расширениеpyd) в питоне на Windows без линковки к pythonXX