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