Просмотр сообщений
|
Страниц: [1]
|
1
|
Qt / 2D и 3D графика / Re: Как увеличить размеры QGraphicsItem?
|
: Март 20, 2021, 07:13
|
В итоге решил вопрос следующим образом: во-первых, для каждого создаваемого айтома переопределил boundingRect так, чтобы занимался минимум месте. Во-вторых, создал еще один "псевдоайтем", который совершенно ничего не рисует, но у которого также переопределен boundingRect - он равен всему полю отрисовки сцены и высчитывается в graphicsView, где с помощью метода scene->itemsBoundingRect() можно получать общий размер, занимаемый айтемами, и передавать этот размер в "псевдоайтем".
|
|
|
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 не выполняется! Есть просто символы, иконки, а реакций никаких нет! Подскажите, где я ошибаюсь?
|
|
|
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); }
|
|
|
|
|