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

c++
Вопрос: Как я могу нарисовать форму, как слеза? Мне нужно рисовать, не используя более одной фигуры (эллипс и многоугольник), потому что QPen будет рисовать для каждой фигуры. Мне нужно объединить фигуры, чтобы создать новую, или сказать QT соединить границу между обеими фигурами, что-то вроде этого: Лучший ответ: Если фигура, которую вы хотите нарисовать, может быть

Вопрос:

Как я могу нарисовать форму, как слеза? Мне нужно рисовать, не используя более одной фигуры (эллипс и многоугольник), потому что QPen будет рисовать для каждой фигуры. Мне нужно объединить фигуры, чтобы создать новую, или сказать QT соединить границу между обеими фигурами, что-то вроде этого:

tear

Лучший ответ:

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

Сначала нам нужно построить 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

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

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

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

Оцените статью
Добавить комментарий