Разбираюсь с рисовкой в Qt, пытаюсь нарисовать свою графическую фигуру, используя QPainterPath
. Для этого создаю класс class PuzzlePiece : public QGraphicsPathItem
. В нём вся логика по отрисовке. Графический объект будет иметь размеры p_size
. Я создаю объект QPainterPath pp;
pp.moveTo(-p_size / 2, -p_size / 2);
pp.lineTo(-p_size / 16, -p_size / 2);
pp.arcTo(-p_size / 8, -p_size / 2 -p_size / 8,
p_size / 8, p_size / 8, 270, -90.0);
pp.arcTo(-p_size / 8, -p_size / 2 -p_size / 8 -p_size / 16,
p_size / 4, p_size / 4, 180, -180.0);
pp.arcTo(0, -p_size / 2 -p_size / 8,
p_size / 8, p_size / 8, 0, -90.0);
pp.lineTo(p_size / 2, -p_size / 2);
На этом этапе отрисовывается лишь часть фигуры (только 3 дуги окружности). Однако, при добавлении ещё одной строки pp.lineTo(p_size / 2, p_size / 2);
добавляется оставшаяся часть (две горизонтальные линии).
Выглядит это как-то так:
Подскажите пожалуйста, почему отрисовка происходит невсегда и от чего это зависит? Спасибо.
Полный код puzzlepiece.cpp:
#include "puzzlepiece.h"
#include <QPainter>
#include <QDebug>
PuzzlePiece::PuzzlePiece(ConnectorPosition north, ConnectorPosition east,
ConnectorPosition south, ConnectorPosition west){
sides[0] = north;
sides[1] = east;
sides[2] = south;
sides[3] = west;
ppix = QPixmap("C:/Users/Public/Pictures/Sample Pictures/Хризантема.jpg");
p_size = 200;
QPainterPath pp;
constructPP(pp);
setPath(pp);
}
//void PuzzlePiece::constructShape(QPainterPath &pp){
// pp.moveTo(-p_size / 2, -p_size / 2);
// switch(sides[0]){
// case None:
// pp.lineTo(p_size / 2, -p_size / 2);
// break;
// case Out:
// pp.lineTo(-p_size / 16, -p_size / 2);
// pp.arcTo(-p_size / 8, -p_size / 2 -p_size / 8,
// p_size / 8, p_size / 8, 270, -90.0);
// pp.arcTo(-p_size / 8, -p_size / 2 -p_size / 8 -p_size / 16,
// p_size / 4, p_size / 4, 180, -180.0);
// pp.arcTo(0, -p_size / 2 -p_size / 8,
// p_size / 8, p_size / 8, 0, -90.0);
// pp.lineTo(p_size / 2, -p_size / 2);
// break;
// case In:
// pp.lineTo(-p_size / 16, -p_size / 2);
// pp.arcTo(-p_size / 8, -p_size / 2,
// p_size / 8, p_size / 8, 90, 90.0);
// pp.arcTo(-p_size / 8, -p_size / 2 -p_size / 16,
// p_size / 4, p_size / 4, 180, 180.0);
// pp.arcTo(0, -p_size / 2,
// p_size / 8, p_size / 8, 0, 90.0);
// pp.lineTo(p_size / 2, -p_size / 2);
// break;
// }
// switch(sides[1]){
// case None:
// pp.lineTo(p_size / 2, p_size / 2);
// break;
// case Out:
// pp.lineTo(p_size / 2 , -p_size / 16);
// pp.arcTo(p_size / 2, -p_size / 8,
// p_size / 8, p_size / 8, 180, -90.0);
// pp.arcTo(p_size / 2 -p_size / 16, -p_size / 8,
// p_size / 4, p_size / 4, 90, -180.0);
// pp.arcTo(p_size / 2, 0,
// p_size / 8, p_size / 8, 270, -90.0);
// pp.lineTo(p_size / 2, p_size / 2);
// break;
// case In:
// pp.lineTo(p_size / 2 , -p_size / 16);
// pp.arcTo(p_size / 2 -p_size / 8, -p_size / 8,
// p_size / 8, p_size / 8, 0, 90.0);
// pp.arcTo(p_size / 2 -p_size / 8 -p_size / 16, -p_size / 8,
// p_size / 4, p_size / 4, 90, 180.0);
// pp.arcTo(p_size / 2 -p_size / 8, 0,
// p_size / 8, p_size / 8, 270, 90.0);
// pp.lineTo(p_size / 2, p_size / 2);
// break;
// }
// switch(sides[2]){
// case None:
// pp.lineTo(-p_size / 2, p_size / 2);
// break;
// case Out:
// pp.lineTo(p_size / 16, p_size / 2);
// pp.arcTo(0, p_size / 2,
// p_size / 8, p_size / 8, 90, -90.0);
// pp.arcTo(-p_size / 8, p_size / 2 -p_size / 16,
// p_size / 4, p_size / 4, 0, -180.0);
// pp.arcTo(-p_size / 8, p_size / 2,
// p_size / 8, p_size / 8, 180, -90.0);
// pp.lineTo(-p_size / 2, p_size / 2);
// break;
// case In:
// pp.lineTo(p_size / 16, p_size / 2);
// pp.arcTo(0, p_size / 2 -p_size / 8,
// p_size / 8, p_size / 8, 270, 90.0);
// pp.arcTo(-p_size / 8, p_size / 2 -p_size / 8 -p_size / 16,
// p_size / 4, p_size / 4, 0, 180.0);
// pp.arcTo(-p_size / 8, p_size / 2 -p_size / 8,
// p_size / 8, p_size / 8, 180, 90.0);
// pp.lineTo(-p_size / 2, p_size / 2);
// break;
// }
// switch(sides[3]){
// case None:
// pp.lineTo(-p_size / 2, -p_size / 2);
// break;
// case Out:
// pp.lineTo(-p_size / 2 , p_size / 16);
// pp.arcTo(-p_size / 2 -p_size / 8, 0,
// p_size / 8, p_size / 8, 0, -90.0);
// pp.arcTo(-p_size / 2 -p_size / 8 -p_size / 16, -p_size / 8,
// p_size / 4, p_size / 4, 270, -180.0);
// pp.arcTo(-p_size / 2 -p_size / 8, -p_size / 8,
// p_size / 8, p_size / 8, 90, -90.0);
// pp.lineTo(-p_size / 2, -p_size / 2);
// break;
// case In:
// pp.lineTo(-p_size / 2 , p_size / 16);
// pp.arcTo(-p_size / 2, 0,
// p_size / 8, p_size / 8, 180, 90.0);
// pp.arcTo(-p_size / 2 -p_size / 16, -p_size / 8,
// p_size / 4, p_size / 4, 270, 180.0);
// pp.arcTo(-p_size / 2, -p_size / 8,
// p_size / 8, p_size / 8, 90, 90);
// pp.lineTo(-p_size / 2, -p_size / 2);
// break;
// }
//}
void PuzzlePiece::constructPP(QPainterPath &pp){
pp.moveTo(-p_size / 2, -p_size / 2);
pp.lineTo(-p_size / 16, -p_size / 2);
pp.arcTo(-p_size / 8, -p_size / 2 -p_size / 8,
p_size / 8, p_size / 8, 270, -90.0);
pp.arcTo(-p_size / 8, -p_size / 2 -p_size / 8 -p_size / 16,
p_size / 4, p_size / 4, 180, -180.0);
pp.arcTo(0, -p_size / 2 -p_size / 8,
p_size / 8, p_size / 8, 0, -90.0);
pp.lineTo(p_size / 2, -p_size / 2);
pp.lineTo(p_size / 2, p_size / 2);
}
void PuzzlePiece::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
painter->setClipPath(path());
painter->setPen(QPen(Qt::black, 3));
QRect b_rect = boundingRect().toRect();
painter->drawPixmap(b_rect.x(), b_rect.y(), pixmap());
painter->drawPath(path());
}
QPixmap PuzzlePiece::pixmap(){
return ppix;
}
void PuzzlePiece::setPixmap(QPixmap &pix){
ppix = pix;
update();
}
Полный код puzzlepiece.h:
#ifndef PUZZLEPIECE_H
#define PUZZLEPIECE_H
#include <QGraphicsPathItem>
class PuzzlePiece : public QGraphicsPathItem
{
public:
enum ConnectorPosition {None, Out, In};
PuzzlePiece(ConnectorPosition, ConnectorPosition, ConnectorPosition, ConnectorPosition);
QPixmap pixmap();
void setPixmap(QPixmap &);
private:
int p_size;
QPixmap ppix;
ConnectorPosition sides[4];
void constructPP(QPainterPath &pp);
void constructShape(QPainterPath &);
void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget = nullptr);
};
#endif // PUZZLEPIECE_H
main.cpp:
#include <QApplication>
#include "configurationdialog.h"
#include <QDebug>
#include <QGraphicsView>
#include "puzzlepiece.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsView view;
QGraphicsScene scene;
scene.addItem(new PuzzlePiece(PuzzlePiece::In, PuzzlePiece::Out,
PuzzlePiece::In, PuzzlePiece::Out));
view.setScene(&scene);
view.show();
// ConfigurationDialog c;
// c.show();
return a.exec();
}
Код помог, у вас ошибка в методе отрисовки.
painter->setClipPath(path());
painter->setPen(QPen(Qt::black, 3));
...
painter->drawPath(path());
Первым действием отрисовки вы ограничиваете область отрисовки контуром пазла и только потом отрисовываете этот контур с толщиной линии 3. По факту получается, что, поскольку у линии толщина 3 пикселя вы видите лишь часть своего контура. Когда вы добавляете строку с отрисовкой вертикальной линии, то изменяется общий размер контура и вы видите те части, которые не видно было раньше.
Правильная отрисовка будет выглядеть так:
void PuzzlePiece::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->setPen(QPen(Qt::black, 3));
painter->drawPath(path());
painter->setClipPath(path());
QRect b_rect = boundingRect().toRect();
painter->drawPixmap(b_rect.x(), b_rect.y(), pixmap());
}
сначала рисуем контур, потом ставим огранчиение по контуру и рисуем туда пиксмап. Пробуйте)
P.S. попробуйте включить опцию антиалиасинга для пэинтера, отрисовка будет на такой пиксельно
painter->setRenderHint(QPainter::Antialiasing);
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Можно ли заменить следующий цикл на какой-то стандартный алгоритм библиотеки?
Написал проверку для input-ов на наличие хотя бы 1-ого символа для того чтобы удалить атрибут disabled с кнопки отправкиВ условии так же указал если...
Вы не указали диалект паскаля! Вот решения для паскаля из стандарта ISO 7185: