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

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: [1]
1  Qt / 2D и 3D графика / Re: Как увеличить размеры QGraphicsItem? : Март 20, 2021, 07:13
В итоге решил вопрос следующим образом: во-первых, для каждого создаваемого айтома переопределил boundingRect так, чтобы занимался минимум месте. Во-вторых, создал еще один "псевдоайтем", который совершенно ничего не рисует, но у которого также переопределен boundingRect - он равен всему полю отрисовки сцены и высчитывается в graphicsView, где с помощью метода scene->itemsBoundingRect() можно получать общий размер, занимаемый айтемами, и передавать этот размер в "псевдоайтем".
2  Qt / 2D и 3D графика / Re: QCustomPlot. Как сделать изменяющийся во времени график? : Март 18, 2021, 17:01
Лучше ответить поздно, чем никогда!

Конкретной цели не было, хотелось выслушать мнение других касательно оптимальных возможностей вывода графиков.
хороший вариант был дан тут: https://www.cyberforum.ru/qt/thread2786560.html, правда, как я понимаю, в таком случае нет доступа к самим данным, и если стереть график, то заново его уже не воссоздать.
3  Qt / 2D и 3D графика / Как увеличить размеры QGraphicsItem? : Март 18, 2021, 16:51
Добрый день!
Пытаюсь через QGraphicsView нарисовать картинку, однако она получается слишком маленькой. Пробовал через setScale, но никаких результатов это не дает (возможно, потому что я на самих виджетах использовал scale для подгона размеров самих айтемов относительно друг друга). Дальше, я знаю крайние координаты, то есть грубо говоря поле прорисовки, однако их использование (через setMimimumSize и setSceneRect) ни к чему не приводят. Пытался искусственно задать, так сказать, окна прорисовки, размеры виджетов и их расположение через функцию scaling_window(double xmin, double ymin, double xmax, double ymax), но она приводит к ошибке. Пытался "растянуть" картинку на весь QGraphicsView через this->fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio); но это также ни к чему не привело.
Подскажите, как можно попробовать решить возникшую проблему?

Код рисования картинки:
mechanism_1.cpp:
Код:
#include "mechanism_1.h"
#include "parts.h"
 
#include <QtMath>
#include <QTimer>
#include <QDebug>
 
Mechanism_1::Mechanism_1(QFont _font, double l1, double l2,
                         double _xa, double _ya, double _xb, double _yb, double _xl, double _yl,
                         double _xc, double _yc, double _xc2, double _yc2,
                         double fi1, double fi2, double al,
                         double _xmin, double _ymin, double _xmax, double _ymax, double _xo1, double _yo1,
                         QWidget *parent) : QGraphicsView(parent)
{
    scene = new Scene();
    this->setScene(scene);
    this->resize(600, 100);
    this->setMinimumSize(600, 100);
 
    this->setRenderHint(QPainter::Antialiasing);    // Устанавливаем сглаживание
    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Отключаем скроллбар по вертикали
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Отключаем скроллбар по горизонтали
    //rscene->setSceneRect(0, 0, 100, 100);   // Устанавливаем размеры графической сцены
    //QRect rect(150, 150, 300, 300);
    this->fitInView(scene->itemsBoundingRect(), Qt::KeepAspectRatio);
    setAlignment(Qt::AlignCenter);
 
//    QRect mainrect(0, 0, 500, 500);
//    //scene->addRect(rect);
//    scene->addRect(mainrect);
    //scaling_window(_xmin, _ymin, _xmax, _ymax);
 
    fi1g = -fi1;
    fi2g = -fi2;
    alg = -al;
 
    xo1 = _xo1;
    yo1 = -_yo1;
    xa = _xa;
    ya = -_ya;
    xb = _xb;
    yb = -_yb;
    xl = _xl;
    yl = -_yl;
    xc = _xc;
    yc = -_yc;
 
    xmin = _xmin;
    ymin = _ymin;
    xmax = _xmax;
    ymax = _ymax;
 
    scale = 1;
 
    Ox = new Arrow(30);
    scene->addItem(Ox);
 
    textX = new Text(_font, QString("x"));
    textX->setPos(xo1 + Ox->getl() - 3 * 0.5 * scale * textX->getHorizontalAdvance(), yo1 + 2 * scale * textX->getHeight());
    textX->setScale(3*scale);
    scene->addItem(textX);
 
    Oy = new Arrow(30);
    Oy->setRotation(-90);
    scene->addItem(Oy);
 
    textY = new Text(_font, QString("y"));
    textY->setPos(xo1 - 6 * scale * textY->getHorizontalAdvance(), yo1 - Oy->getl() + 3 * 0.5 * scale * textY->getHeight());
    textY->setScale(3*scale);
    scene->addItem(textY);
 
    O1 = new Hinge();
    O1->setPos(xo1, yo1);
    O1->setScale(scale);
    scene->addItem(O1);
 
    O1A = new Crank(l1);
    O1A->setPos(xo1, yo1);
    O1A->setRotation(fi1g);
    scene->addItem(O1A);
 
    A = new FixedHinge();
    A->setPos(xa, ya);
    A->setScale(scale);
    scene->addItem(A);
 
 
    B = new Slider();
    B->setPos(xb, yb);
    B->setRotation(alg);
    B->setScale(scale);
    scene->addItem(B);
 
    L = new FixedHinge();
    L->setPos(xl, yl);
    L->setScale(scale);
    scene->addItem(L);
 
    l = new DoshLine(300);
    l->setPos(xl, yl);
    l->setRotation(alg);
    l->setScale(scale);
    scene->addItem(l);
 
    ABC = new Polygon(_xc2, _yc2, l2);
    ABC->setPos(xa, ya);
    ABC->setRotation(fi2g);
    scene->addItem(ABC);
 
    AB = new Crank(l2);
    AB->setPos(xa, ya);
    AB->setRotation(fi2g);
    scene->addItem(AB);
    AB->hide();
 
    textO1 = new Text(_font, QString("O1"));
    textO1->setPos(xo1 - 3 * scale * textO1->getHorizontalAdvance(), yo1 + 3 * scale * 0.5 * textO1->getHeight());
    textO1->setScale(3*scale);
    scene->addItem(textO1);
 
    textA = new Text(_font, QString("A"));
    textA->setPos(xa - 3 * scale * textA->getHorizontalAdvance(), ya);
    textA->setScale(3*scale);
    scene->addItem(textA);
 
    textB = new Text(_font, QString("B"));
    textB->setPos(xb + 3 * scale * textB->getHorizontalAdvance(), yb);
    textB->setScale(3*scale);
    scene->addItem(textB);
 
    textC = new Text(_font, QString("C"));
    textC->setPos(xc - 3 * scale * textC->getHorizontalAdvance(), yc);
    textC->setScale(3*scale);
    scene->addItem(textC);
 
    textL = new Text(_font, QString("L"));
    textL->setPos(xl + 3 * scale * textL->getHorizontalAdvance(), yl + scale * textL->getHeight());
    textL->setScale(3*scale);
    scene->addItem(textL);
 
//    scene = new Scene();
//    this->setScene(scene);
//    //this->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
 
//    if (qAbs(_xmin - _xmax) != 0 and qAbs(_ymin - _ymax) != 0) {
//        this->resize(500,500);
////        this->setMinimumSize(qAbs(_xmin - _xmax), qAbs(_ymin - _ymax));
////        scene->setSceneRect(_xmin, _ymin, qAbs(_xmin - _xmax), - qAbs(_ymin - _ymax));
//        scaling_window(_xmin, _ymin, _xmax, _ymax, width(), height());
////        scene->setSceneRect(_xmin * (1/index), _ymax * (1/index),
////                            qAbs(_xmin - _xmax) * (1/index), qAbs(_ymin - _ymax) * (1/index));
//        scene->setSceneRect(0, 0, width(), -height());
//    } else {
////        this->resize(2*(l1 + l2), 2*(l1 + l2));
////        this->setMinimumSize(2*(l1 + l2), 2*(l1 + l2));
////        scene->setSceneRect(-(l1+l2), -(l1+l2), 2*(l1 + l2), 2*(l1 + l2));
//        scene->setSceneRect(-(l1+l2), -(l1+l2), width(), - height());
//    }
 
//    QRect rect(0, 0, width(), -height());
//    scene->addRect(rect);
 
//    this->setRenderHint(QPainter::Antialiasing);    // Устанавливаем сглаживание
//    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Отключаем скроллбар по вертикали
//    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Отключаем скроллбар по горизонтали
 
//    fi1g = -fi1;
//    fi2g = fi2;
//    alg = al;
 
//    xo1 = _xo1 * (1/index);
//    yo1 = -_yo1 * (1/index);
//    xa = _xa * (1/index);
//    ya = -_ya * (1/index);
//    xb = _xb * (1/index);
//    yb = -_yb;
 
//    xmin = _xmin * (1/index);
//    ymin = _ymin * (1/index);
//    xmax = _xmax * (1/index);
//    ymax = _ymax * (1/index);
 
//    O1 = new Hinge();
//    O1->setPos(xo1, yo1);
//    scene->addItem(O1);
 
//    O1A = new Crank(l1*(1/index));
//    O1A->setPos(xo1, yo1);
//    O1A->setRotation(fi1g);
//    scene->addItem(O1A);
 
//    A = new FixedHinge();
//    A->setPos(xa, ya);
//    scene->addItem(A);
 
//    AB = new Crank(l2*(1/index));
//    AB->setPos(xa, ya);
//    AB->setRotation(fi2g);
//    scene->addItem(AB);
 
//    B = new Slider();
//    B->setPos(xb, yb);
//    B->setRotation(al);
    //    scene->addItem(B);
}
 
void Mechanism_1::scaling_window(double xmin, double ymin, double xmax, double ymax)
{
    double relation_x = qAbs(xmin - xmax) / width();
    double relation_y = qAbs(ymin - ymax) / height();
 
    qDebug() << "relation_x = " << relation_x << ", relation_y = " << relation_y << Qt::endl;
    qDebug() << "dx = " << qAbs(xmin - xmax) << ", dy = " << qAbs(ymin - ymax) << Qt::endl;
    qDebug() << "xmin = " << xmin << ", ymin = " << ymin << ", xmax = " << xmax << ", ymax = " << ymax << Qt::endl;
    qDebug() << "height = " << height() << ", width = " << width() << Qt::endl;
 
    if (relation_x > relation_y)
        index = relation_y;
    else
        index = relation_x;
}
parts.cpp:
Код:
#include "parts.h"
 
#include <QFont>
#include <QDebug>
#include <QtMath>
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Hinge~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Hinge::Hinge() : QGraphicsObject() {}
 
QRectF Hinge::boundingRect() const
{
    return QRectF(-100, -100, 200, 200);
}
 
void Hinge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
 
    painter->setBrush(Qt::NoBrush);
    painter->setPen(QPen(Qt::black, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    painter->rotate(60.0);
    painter->drawLine(0, 0, 60, 0);
    painter->translate(60, 0);
    painter->rotate(120.0);
    painter->drawLine(0, 0, 60, 0);
    painter->drawLine(-10, 0, 70, 0);
    painter->setPen(Qt::NoPen);
    painter->setBrush(QBrush(Qt::black, Qt::BDiagPattern));
    painter->drawRect(-10, 0, 80, -25);
    painter->setBrush(Qt::NoBrush);
    painter->setPen(QPen(Qt::black, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    painter->translate(60, 0);
    painter->rotate(120.0);
    painter->drawLine(0, 0, 60, 0);
    painter->translate(60, 0);
    painter->rotate(60.0);
    painter->drawEllipse(-40, -40, 80, 80);
    painter->drawEllipse(-25, -25, 50, 50);
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~FixedHinge~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
FixedHinge::FixedHinge()
{
 
}
 
QRectF FixedHinge::boundingRect() const
{
    return QRectF(-250, -250, 500, 500);
}
 
void FixedHinge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
 
    painter->setBrush(Qt::NoBrush);
    painter->setPen(QPen(Qt::black, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    painter->drawEllipse(-25, -25, 50, 50);
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Slider~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Slider::Slider() { }
 
QRectF Slider::boundingRect() const
{
    return QRectF(-250, -250, 500, 500);
}
 
void Slider::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
 
    painter->setBrush(Qt::NoBrush);
    painter->setPen(QPen(Qt::black, 5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    painter->drawRect(-70, -50, 140, 100);
    painter->drawEllipse(-25, -25, 50, 50);
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Crank~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Crank::Crank(double L) : QGraphicsObject()
{
    l = L;
}
 
QRectF Crank::boundingRect() const
{
    return QRectF(-250, -250, 500, 500);
}
 
void Crank::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
 
    painter->setBrush(Qt::NoBrush);
    painter->setPen(QPen(Qt::black, 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    painter->drawLine(0, 0, l, 0);
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Пунктирная прямая~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
DoshLine::DoshLine(double L)
{
    l = L;
    rect = QRectF(-l*0.5, -l*0.5, l, l);
}
 
QRectF DoshLine::boundingRect() const
{
    return rect;
}
 
void DoshLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
 
    painter->setBrush(Qt::NoBrush);
    painter->setPen(QPen(Qt::black, 5, Qt::DashLine, Qt::RoundCap, Qt::RoundJoin));
    painter->drawLine(0, 0, l, 0);
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Стрелка~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Arrow::Arrow(double L, double Al)
{
    l = L;
    al = Al;
    rect = QRectF(-l*0.5, -l*0.5, l, l);
}
 
QRectF Arrow::boundingRect() const
{
    return rect;
}
 
void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
 
    painter->setBrush(Qt::NoBrush);
    painter->setPen(QPen(color, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    painter->drawLine(0, 0, l, 0);
    painter->translate(l, 0);
    painter->rotate(180 - al);
    painter->drawLine(0, 0, l* 0.2, 0);
    painter->rotate(2*al);
    painter->drawLine(0, 0, l* 0.2, 0);
    painter->rotate(180 - al);
    painter->translate(-l, 0);
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Полигон треугольник~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Polygon::Polygon(double _xc2, double _yc2, double _l2)
{
    xc2 = _xc2;
    yc2 = -_yc2;
    l = _l2;
 
    poly.append(QPoint(0, 0));
    poly.append(QPoint(l, 0));
    poly.append(QPoint(xc2, yc2));
 
 
    if (xc2 * l >= 0)
        (qAbs(xc2) >= qAbs(l)) ? rect = QRectF(0, 0, xc2, yc2) : rect = QRectF(0, 0, l, yc2);
    else
        (xc2 >= 0) ? rect = QRectF(xc2, 0, -(xc2 + qAbs(l)), yc2) : rect = QRectF(xc2, 0, qAbs(xc2) + l, yc2);
}
 
QRectF Polygon::boundingRect() const
{
    return rect;
}
 
void Polygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
 
    painter->setBrush(QBrush(Qt::blue, Qt::BDiagPattern));
    painter->setPen(QPen(Qt::red, 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    //qDebug() << "Polygon: " << poly << Qt::endl;
 
    painter->drawPolygon(poly);
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Текст~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Text::Text(QFont Font, QString Str)
{
    font = Font;
    font.setBold(true);
    fm = new QFontMetrics(font);
    str = Str;
}
 
QRectF Text::boundingRect() const
{
    return QRectF(0, 0, fm->horizontalAdvance(str), -fm->height());
}
 
void Text::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    Q_UNUSED(widget);
 
    painter->setPen(QPen(Qt::black, fm->height(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    painter->setFont(font);
    painter->drawText(0, 0, tr("%1").arg(str));
}
 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Сцена~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
Scene::Scene(QObject *parent) : QGraphicsScene(parent) {}
Scene::~Scene() {}
4  Qt / 2D и 3D графика / QCustomPlot. Как сделать изменяющийся во времени график? : Февраль 21, 2021, 12:29
Добрый день!
Хочу реализовать график, который изменяет свой вид с течением времени. Так сказать, не статический, а динамический.
Пока что додумался до трех способов:
1. В классе есть вектор QVector<double> key, value. Каждый раз, когда срабатывает timeout таймера, вызывается слот, в котором к векторам через append добавляется новый элемент. При этом у нас есть только один график и он просто каждый раз перерисовывается. Таким образом, у нас график как бы ползет. Плюс этого способа, как мне кажется, это то, что то, что уже нарисовано, остается таким, какое оно есть и после перерисовки. Минус - затрата памяти и времени, ведь для этого постоянно приходится увеличивать массив элементов, то есть наши вектора.
2. У нас нет начальных вектором аргумента и значения, зато в слоте у нас создается каждый раз два новых вектора, состоящих из двух элементов - первый элемент это последний элемент в предыдущем вызове, а второй элемент - кончик новой части графика, так сказать, которая после отрисовки появится на экране. При этом эти вектора загружаются в каждый раз технически новый график. В итоге, реально график рисуется кусочно. Плюс, вроде как, что не приходится каждый раз меня размер массивов, минус - "ершистость" графика.
3. Создаем в классе два вектора на два значения (предположим, что мы рисует просто линейный график). Первое значение - реальная начальная точка. А второе значение всегда разное. Так как у нас график рисуется через прямые, проходящие через контрольные точки, за счет того, что вторая точка каждый раз разная, наш график визуально изменяется и вместе с тем не приходится меня размер массивов. Мы просто удаляем последний (второй) элемент и добавляем новый. Ну, и перерисовываем. Однако, во-первых, график как бы скочет туда сюда из-за таких перерисовок (совсем чуть-чуть, но все же), а во-вторых, оно так удобно пока функция линейная.

В связи с этим вопрос: как все-таки лучше рисовать графики изменяющиеся во времени, чтобы при этом был минимум затрат памяти и времени на перерисовку?

P.S.: если объяснено непонятно и надо выложить код - напишите в комменте. Изначально решил не выкладывать, чтобы не делать сообщение слишком большим.
5  Qt / Пользовательский интерфейс (GUI) / Как скрыть QToolBar и QMenu : Февраль 16, 2021, 13:18
Добрый день!
Пытаюсь реализовать систему меню с возможностью выбора вкладки и последующим возвратом обратно в меню (например, через кнопку стрелочка). Причем во всех вкладках, кроме самого меню, вверху окна есть строка с QMenu и QToolBar. Пусть там, для простоты, будет возможность создать новое окно.
У меня это реализовано через QMainWindow и QWidget-ы. QMainWindow - основное окно, в котором и находится, например, два виджета: один виджет "меню", второй виджет "выбранный пункт", а новое окно реализуется через QAction и запихано в QMenu и в QToolBar. Смена виджетов происходит через сигналы и слоты. (и в том, и в другом виджете есть кнопочки для переключения между ними).
Итак, ситуация вот какая: когда у меня запускает прога, у меня есть открыто меню (без QMenu и QToolBar). Затем я выбираю пункт и перехожу в следующий виджет (виджет меню у меня скрывается hide-ом). В этом виджете сверху у меня уже появляются QMenu и QToolBar, причем QAction тоже выполняется (при нажатии появляются новые окошки). Затем я перехожу обратно в меню (предыдущий виджет скрывается, QTooBar и QMenu становятся невидимыми через setVisible(false)). А потом снова в мой виджет. QMenu и QToolBar появляются... но не работают! QAction не выполняется! Есть просто символы, иконки, а реакций никаких нет! Подскажите, где я ошибаюсь?
6  Qt / 2D и 3D графика / Re: QGraphicsObject. Ошибка отрисовки : Январь 21, 2021, 11:54
В итоге все исправилось после указания в boundingRect больший размер отрисовки.
7  Qt / 2D и 3D графика / QGraphicsObject. Ошибка отрисовки : Январь 19, 2021, 00:17
При анимировании итемов на сцене возникает интересный лаг: прямоугольник оставляет след, а вертикальная прямая, будто выходя за область отрисовки, оставляет свой конец неподвижным. К сожалению, понять, как сюда выкладывать картинки мне так и не удалось, поэтому вот ссылка на папку с фотографиями:
https://drive.google.com/drive/folders/18NO_BVtCff0J7ik67DP3LlIpQpsexy_y?usp=sharing
Первое, что приходит на ум - двойная буферизация, но вроде как она реализована внутри самих виджитов, да и мерцания, в общем-то, у меня нет, так что вряд ли проблема в ней.
Отмечу, что если, например, сделать прямоугольник поменьше или вообще убрать, то следов справа не остается и все двигается плавно и ровно.
Кружочек с прямоугольником (и соответственно желтая и синяя прямые) реализованы отдельным классом, их отрисовкой занимается paint.
Анимация происходит при срабатывании таймера, к сигналу которого подключен слот класса, унаследованного от QGraphicsView (на котором вся эта картина и происходит). Этот слот просто меняет позицию "особой точки" по х, после чего сдвигает класс прямоугольника, кружочка и двух прямых в новое положение особой точки (нижний конец правого черного отрезка, соединяющего кружочек в прямоугольничке с верхним кружочком, тоже соответственно смещается в новую позицию особой точки, создавая иллюзию единой конструкции).
Как думаете, с чем могут быть связанные такие лаги?

p.s.: видимо, скоро я стану одним из частых гостей форума
8  Qt / 2D и 3D графика / Re: QGraphicsScene. Несоответствие координат. : Январь 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");
}
9  Qt / 2D и 3D графика / QGraphicsScene. Несоответствие координат. : Январь 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 и у. Мне ужасно интересно, где же все-таки ошибка! Или я чего-то не понимаю?   Непонимающий
10  Qt / 2D и 3D графика / Re: Как сделать часть объекта QPainter невидимой? : Январь 10, 2021, 20:58
Идея с QRegion и setClipRegion хорошая, спасибо за наводку! Однако возник тогда такой, казалось бы, глупый вопрос: когда я создаю QRegion типа эллипса, ну, то есть обычный кружок, выделяется и впоследствии стирается область вне круга. Из документации не очень понятно, как указать, чтобы выделялся регион не вне окружности, а как раз таки внутри. В интернете почему-то этот, как мне кажется, вполне естественный вопрос, тоже не разбирается, либо я плохо ищу, конечно. Возможно, Вы подскажите как быть?
Помимо прочего, как я понимаю, регион может быть также образован перекрытием двух областей и использованием одним из трех методов: xored, united, intersected. Однако и такими манипулированиями не получается вырезать область внутри! В том числе не получается и вырезать как бы колечко, бублик, образованный маленькой и большой окружностью, зато можно вырезать все вокруг Улыбающийся
И последний вопрос, ответ на который мне также найти самостоятельно не удалось: я правильно понимаю, что внутри большой окружности не получится вырезать только лишний кусок треугольника, а маленькую окружность оставить на месте?
Еще раз большое спасибо за ответ!
11  Qt / 2D и 3D графика / Как сделать часть объекта QPainter невидимой? : Январь 08, 2021, 13:21
Добрый день! Пытаюсь нарисовать картинку: две окружности, вложенные друг в друга, и треугольник, одна из вершин которого является центром этих двух окружностей. Хочется, чтобы та часть треугольника, которая как бы находится внутри окружностей, была бы невидимой. Подскажите, как добиться такого эффекта? Непонимающий  Через setCompositionMode, к сожалению, у меня не получилось.  Плачущий Возможно, задачу решить гораздо легче через QGraphicsItem. Заранее спасибо огромное за помощь!
h:
Код:
class SliderCrankLinkage : public QWidget
{
    Q_OBJECT
public:
    explicit SliderCrankLinkage(QWidget *parent = nullptr);
protected:
    void paintEvent(QPaintEvent* e);
};

срр:
Код:
void SliderCrankLinkage::paintEvent(QPaintEvent *e)
{
    Q_UNUSED(e);

    QPainter pbearing(this);
    pbearing.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);

    QTransform transform;
    transform.translate(150, 150);
    pbearing.setWorldTransform(transform);
    pbearing.drawEllipse(-40, -40, 80, 80);
    pbearing.drawEllipse(-25, -25, 50, 50);
    transform.rotate(+60.0);
    pbearing.setWorldTransform(transform);
    pbearing.drawLine(AB);
    transform.rotate(+60.0);
    pbearing.setWorldTransform(transform);
    pbearing.drawLine(BC);
    transform.rotate(-60.0);
    transform.translate(60.0, 0);
    transform.rotate(+120.0);
    pbearing.setWorldTransform(transform);
    pbearing.drawLine(CA);
    transform.translate(30.0, 0);
    pbearing.setWorldTransform(transform);
    pbearing.drawLine(50, 0, -50, 0);
    pbearing.setPen(Qt::NoPen);
    pbearing.setBrush(QBrush(Qt::black, Qt::BDiagPattern));
    pbearing.drawRect(50, 0, -100, -25);
}

Страниц: [1]

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