Что нового?

Welcome to Все о цифровых товарах продажа цифровых товаров - All about digital goods selling digital goods - Управляющий партнер юридической группы Golo Ltd - Managing partner of the Golo Ltd legal group

Join us now to get access to all our features. Once registered and logged in, you will be able to create topics, post replies to existing threads, give reputation to your fellow members, get your own private messenger, and so, so much more. It's also quick and totally free, so what are you waiting for?

Ask question

Ask Questions and Get Answers from Our Community

Answer

Answer Questions and Become an Expert on Your Topic

Contact Staff

Our Experts are Ready to Answer your Questions

QGraphicsScene. Несоответствие координат - C++ Qt

Krystofer

Юнга
Регистрация
22 Авг 2020
Сообщения
2,078
Реакции
0
Баллы
5,005
Credits
160
Native language | Родной язык
Русский
На сцене есть два итема. Хочется, чтобы их начала координат совпадали с началом координат сцены, но почему-то добиться этого не получается. Пожалуйста, подскажите, где же у меня допущена ошибка?

SliderCrankLinkage.h:
:

Код:
class SliderCrankLinkage : public QGraphicsView
{
public:
    SliderCrankLinkage(QWidget* parent = nullptr);

    QGraphicsScene* scene;
    Link* link;
    GraphicsBearing* bearing;
};

SliderCrankLinkage.cpp:
:

Код:
SliderCrankLinkage::SliderCrankLinkage(QWidget *parent) : QGraphicsView(parent)
{
    scene = new QGraphicsScene(this);
    QRect rect(-300, -300, 600, 600);
    scene->addRect(rect);

    QPoint O(0, 0), A(100, 0), B(-300, 200), E(200, 0), M(0, 200);

    QGraphicsLineItem* Ox = new QGraphicsLineItem(0, 0, 200, 0);
    Ox->setPen(QPen(Qt::red, 10, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    QGraphicsLineItem* Oy = new QGraphicsLineItem(0, 0, 0, 200);
    Oy->setPen(QPen(Qt::red, 10, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    scene->addItem(Ox);
    scene->addItem(Oy);

    QGraphicsObject* link = new Link(A, B);
    scene->addItem(link);
    link->setPos(-A.x(), -A.y());

    QPointF OriginPoint = link->pos();
    QGraphicsObject* bearing = new GraphicsBearing(O);
    QLineF nOx(O, E), nOy(O, M);
    QGraphicsLineItem* newOx = new QGraphicsLineItem(nOx);
    newOx->setPen(QPen(Qt::darkCyan, 7, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    QGraphicsLineItem* newOy = new QGraphicsLineItem(nOy);
    newOy->setPen(QPen(Qt::darkCyan, 7, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    scene->addItem(newOx);
    scene->addItem(newOy);

//ПРОБЛЕМА ТУТ --->
    scene->addItem(bearing);

//    QPointF OriginPoint = link->pos();
//    bearing->setPos(OriginPoint);

    QGraphicsLineItem* minusOx = new QGraphicsLineItem(0, 0, -200, 0);
    minusOx->setPen(QPen(Qt::yellow, 10, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    QGraphicsLineItem* minusOy = new QGraphicsLineItem(0, 0, 0, -200);
    minusOy->setPen(QPen(Qt::yellow, 10, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    scene->addItem(minusOx);
    scene->addItem(minusOy);

    this->setScene(scene);
    this->setRenderHint(QPainter::Antialiasing);
    this->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
    this->setBackgroundBrush(QColor(230, 200, 167));
    this->setWindowTitle("Another name");
}

GraphicsBearing.h:
:

Код:
class GraphicsBearing : public QGraphicsObject
{
public:
    GraphicsBearing(QPoint O = QPoint(0, 0), QGraphicsItem *parent = nullptr);
    GraphicsBearing(QPointF O = QPoint(0, 0), QGraphicsItem *parent = nullptr);

    QRectF boundingRect() const override;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
    QPoint O;
    QPointF OF;
};

GraphicsBearing.cpp:
:

Код:
GraphicsBearing::GraphicsBearing(QPoint point, QGraphicsItem *parent) : QGraphicsObject(parent)
{
    O = point;
}

GraphicsBearing::GraphicsBearing(QPointF point, QGraphicsItem *parent)
{
    OF = point;
}

QRectF GraphicsBearing::boundingRect() const
{
    return QRectF(0, 0, 110, 130);
}

void GraphicsBearing::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    painter->setPen(QPen(Qt::black, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    QLine AB(0, 0, 60, 0), BC(0, 0, 60, 0), CA(0, 0, 60, 0);

    if (O.isNull())
        painter->translate(OF);
    else
        painter->translate(O);
    painter->translate(55, 65);
    painter->rotate(+60.0);
    painter->drawLine(AB);

    painter->rotate(+60.0);
    painter->drawLine(BC);
    painter->rotate(-60.0);
    painter->translate(60.0, 0);
    painter->rotate(+120.0);
    painter->drawLine(CA);

    painter->translate(30.0, 0);
    painter->drawLine(50, 0, -50, 0);
    painter->setPen(Qt::NoPen);
    painter->setBrush(QBrush(Qt::black, Qt::BDiagPattern));
    painter->drawRect(50, 0, -100, -25);

    painter->translate(-30.0, 0);
    painter->rotate(-120.0);
    painter->translate(-60.0, 0);
    painter->rotate(-60.0);
    painter->setPen(QPen(Qt::black, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    painter->setBrush(Qt::NoBrush);
    painter->drawEllipse(-40, -40, 80, 80);
    painter->drawEllipse(-25, -25, 50, 50);

    painter->setPen(Qt::magenta);
    painter->drawLine(0, 0, 200, 0);
    painter->drawLine(0, 0, 0, 200);
}

Насколько я понимаю, вообще-то когда я на сцену добавляю итем, начало координат этого итема как раз таки должно совпадать с началом координат сцены! Однако почему-то bearing упорно игнорирует вообще всякое существование начала координат сцены (точки О для простоты), кроме тех, на которых он появился с самого начала! С link-ом была похожая проблема, но все-таки в конце концов как-то удалось выкрутиться и добиться того, чтобы link, являющийся обычным отрезком, начинался бы из начала координат, а вот с bearing-ом ну ни в какую не выходит!!! Игнорируются все методы, причем, что самое интересное, судя по отладке, bearing реально располагается в начале координат! Однако множественное рисование прямых вдоль осей х и у, сходящихся всегда в точке (0, 0), убеждает, что все-таки начало координат находится в другом месте, не там, где bearing! Для наглядности внутри самого класса bearing тоже есть прямые, идущие вдоль x и у. Мне ужасно интересно, где же все-таки ошибка! Или я чего-то не понимаю?:scratch:

Добавлено через 1 час 3 минуты
А впрочем, знаете, ни черта с link-ом проблема не решилась. Если сделать еще один link, то программа вылетает с ошибкой:
Приложение остановлено, так как оно получило сигнал от операционной системы.

Сигнал:
SIGSEGV
Назначение:
Segmentation fault
Вроде эта ошибка должна означать, что я вызываю нулевой указатель, но что именно за указатель - непонятно, потому что сам новый link (linkBC) все-таки есть и объявлен, судя по отладке. Мне кажется, эти проблемы - одного поля ягоды. Надеюсь, я просто не понимаю, как работают QGraphicsScene и QGraphicsItem.

Link.h:
:

Код:
class Link : public QGraphicsObject
{
    Q_OBJECT
public:
    explicit Link(int x1, int y1, int x2, int y2, QGraphicsItem *parent = nullptr);
    explicit Link(QPoint A, QPoint B, QGraphicsItem *parent = nullptr);
    QRectF boundingRect() const override;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
//    void setPoint1(int x, int y);
//    void setPoint2(int x, int y);
private:
    QPoint point1;
    QPoint point2;
};

Link.cpp:
:

Код:
Link::Link(int x1, int y1, int x2, int y2, QGraphicsItem *parent) : QGraphicsObject(parent)
{
    QGraphicsLineItem* Ox = new QGraphicsLineItem(200, 0, 0, 0, this);
    Ox->setPen(QPen(Qt::yellow, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    QGraphicsLineItem* Oy = new QGraphicsLineItem(0, 200, 0, 0, this);
    Oy->setPen(QPen(Qt::yellow, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    point1.setX(x1);
    point1.setY(y1);
    point2.setX(x2);
    point2.setY(y2);
}

Link::Link(QPoint A, QPoint B, QGraphicsItem *parent) : QGraphicsObject(parent)
{
    point1 = A;
    point2 = B;
}

QRectF Link::boundingRect() const
{
    int x, y;
    if (point1.x()*point2.x() >= 0)
        x = abs(point1.x() - point2.x());
    else
        x = abs(point1.x()) + abs(point2.x());
    if (point1.y()*point2.y() >= 0)
        y = abs(point1.y() - point2.y());
    else
        y = abs(point1.y()) + abs(point2.y());
    return QRectF(0, 0, x, y);
}

void Link::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
    QLine line(point1.x(), point1.y(), point2.x(), point2.y());
    painter->setPen(QPen(Qt::black, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    painter->drawLine(line);
    painter->translate(point1);
    painter->setPen(Qt::blue);
    painter->drawLine(-200, 0, 200, 0);
    painter->drawLine(0, -200, 0, 200);
}

SliderCrankLinkage.cpp после добавления linkBC:
:

Код:
SliderCrankLinkage::SliderCrankLinkage(QWidget *parent) : QGraphicsView(parent)
{
    scene = new QGraphicsScene(this);
    QRect rect(-300, -300, 600, 600);
    scene->addRect(rect);

    QPoint O(0, 0), A(100, 0), B(-300, 200), C(300, 300), E(200, 0), M(0, 200);

    QGraphicsLineItem* Ox = new QGraphicsLineItem(0, 0, 200, 0);
    Ox->setPen(QPen(Qt::red, 10, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    QGraphicsLineItem* Oy = new QGraphicsLineItem(0, 0, 0, 200);
    Oy->setPen(QPen(Qt::red, 10, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    scene->addItem(Ox);
    scene->addItem(Oy);

    QGraphicsObject* linkAB = new Link(A, B);
    scene->addItem(linkAB);
    linkAB->setPos(-A.x(), -A.y());

    QGraphicsObject* linkBC = new Link(B, C);
    scene->addItem(linkBC);
    //linkBC->setPos(B);

    QPointF OriginPoint = link->pos();
    QGraphicsObject* bearing = new GraphicsBearing(O);
    QLineF nOx(O, E), nOy(O, M);
    QGraphicsLineItem* newOx = new QGraphicsLineItem(nOx);
    newOx->setPen(QPen(Qt::darkCyan, 7, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    QGraphicsLineItem* newOy = new QGraphicsLineItem(nOy);
    newOy->setPen(QPen(Qt::darkCyan, 7, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    scene->addItem(newOx);
    scene->addItem(newOy);
    scene->addItem(bearing);
//    QPointF OriginPoint = link->pos();
//    bearing->setPos(OriginPoint);

    QGraphicsLineItem* minusOx = new QGraphicsLineItem(0, 0, -200, 0);
    minusOx->setPen(QPen(Qt::yellow, 10, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    QGraphicsLineItem* minusOy = new QGraphicsLineItem(0, 0, 0, -200);
    minusOy->setPen(QPen(Qt::yellow, 10, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    scene->addItem(minusOx);
    scene->addItem(minusOy);

    this->setScene(scene);
    this->setRenderHint(QPainter::Antialiasing);
    this->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
    this->setBackgroundBrush(QColor(230, 200, 167));
    this->setWindowTitle("Another name");
}

 
shape1
shape2
shape3
shape4
shape7
shape8