Как рисовать пользовательские фигуры (например, слезу) в Qt с помощью QPainter или QPainterPath, используя одну фигуру или группу фигур

У меня есть этот простой вопрос, я не могу нарисовать фигуру, как слеза, но без использования более одной фигуры (эллипс и многоугольник), потому что QPen рисует для каждой фигуры, я хочу что-то вроде объединения фигур для создания новой или сказать QT, что вокруг границы между обеими фигурами, для получения дополнительной информации о том, что я хочу видеть изображение, я хочу создать шабе:https://docs.google.com/open?id=0Bxb0hT_U-KqJSHZUMTF2eFlOYzg

скажите мне, если вы можете увидеть изображение и понять, что я хочу, и спасибо за вашу помощь.

2 ответов


если фигура, которую вы хотите нарисовать, может быть представлена в виде слоев других фигур, как с изображением, с которым вы связаны, это довольно легко сделать:

Сначала нам нужно построить QPainterPath для представления внешнего края формы. Мы строим его, наслаивая более простые формы; в случае вашего примера нам нужен круг и Квадрат. Обратите внимание на использование QPainterPath::setFillRule(Qt::WindingFill): это позже повлияет на то, как путь окрашен (попробуйте удалить его, чтобы увидеть разница!).

QPainterPath OuterPath;
OuterPath.setFillRule(Qt::WindingFill);
OuterPath.addEllipse(QPointF(60, 60), 50, 50);
OuterPath.addRect(60, 10, 50, 50);

С приведенным вами примером нам также необходимо удалить круговую область из центра нашей заполненной формы. Давайте представим эту внутреннюю "границу" как QPainterPath и затем использовать QPainterPath::subtracted() вычесть InnerPath С OuterPath и произведите нашу окончательную форму:

QPainterPath InnerPath;
InnerPath.addEllipse(QPointF(60, 60), 20, 20);

QPainterPath FillPath = OuterPath.subtracted(InnerPath);

как только мы построили пути формы, нам нужно использовать их для заполнения / контура формы. Давайте сначала создадим QPainter и установите его для использования сглаживание:

QPainter Painter(this);
Painter.setRenderHint(QPainter::Antialiasing);

затем нам нужно заполнить форму, которую мы построили:

Painter.fillPath(FillPath, Qt::blue);

наконец, давайте нарисуем контуры. Обратите внимание, что, поскольку у нас есть отдельные пути для внутренней и внешней границ, мы можем погладить каждую границу с разной толщиной линии. Обратите внимание также на использование QPainterPath::simplified(): это преобразует набор слоистых фигур в один QPainterPath который не имеет пересечений:

Painter.strokePath(OuterPath.simplified(), QPen(Qt::black, 1));
Painter.strokePath(InnerPath, QPen(Qt::black, 3));

если мы положим все это вместе это выглядит так:

void Shape::paintEvent(QPaintEvent *)
{
  QPainterPath OuterPath;
  OuterPath.setFillRule(Qt::WindingFill);
  OuterPath.addEllipse(QPointF(60, 60), 50, 50);
  OuterPath.addRect(60, 10, 50, 50);

  QPainterPath InnerPath;
  InnerPath.addEllipse(QPointF(60, 60), 20, 20);

  QPainterPath FillPath = OuterPath.subtracted(InnerPath);

  QPainter Painter(this);
  Painter.setRenderHint(QPainter::Antialiasing);

  Painter.fillPath(FillPath, Qt::blue);
  Painter.strokePath(OuterPath.simplified(), QPen(Qt::black, 1));
  Painter.strokePath(InnerPath, QPen(Qt::black, 3));
}

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

  1. сделать изображение в программе векторного редактирования, как Inkscape (бесплатно), сохранить его как.svg-файл, а затем загрузите его в QGraphicsSvgItem. (Вот что бы я сделал.)

  2. посмотреть QPainterPath::cubicTo(), что позволяет сделать кривую Безье