Russian Qt Forum
Ноябрь 22, 2024, 10:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QGraphicsScene. Несоответствие координат.  (Прочитано 3013 раз)
Lenidoxll
Новичок

Offline Offline

Сообщений: 11


Просмотр профиля
« : Январь 10, 2021, 22:48 »

На сцене есть два итема. Хочется, чтобы их начала координат совпадали с началом координат сцены, но почему-то добиться этого не получается. Пожалуйста, подскажите, где же у меня допущена ошибка?

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 и у. Мне ужасно интересно, где же все-таки ошибка! Или я чего-то не понимаю?   Непонимающий
Записан
Lenidoxll
Новичок

Offline Offline

Сообщений: 11


Просмотр профиля
« Ответ #1 : Январь 11, 2021, 00:07 »

А впрочем, знаете, ни черта с 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");
}
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #2 : Январь 12, 2021, 12:58 »

Центр координат сцены (точка 0,0) - это по умолчанию центр экрана.
Почему-то bearing->setPos(...) в коде закомментирован, а значит, по умолчанию он будет помещён в центр.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.049 секунд. Запросов: 22.