Solved First app, trying to connect QGraphicsLineItems to MainWindow slot.
-
Hi,
How are you generating these tiles out of your dataset ?
-
@SGaist Hello, the user selects a file, that is processed and the dataset (Unfold class) is created, then the pattern is created into a QGraphicsScene from those data. For each piece I create a piece with a title (a TitleItem derived from a QGraphicsTextItem that can be selected and moved to move the whole piece) and the lines (LineItem from QGraphicsLineITem) and numbers (QGraphicsSimpleTextItem) are its children.
void Unfold::displayUI(QGraphicsView* vue, QSlider* hSlider) { QGraphicsScene* scene = new QGraphicsScene; rSlider = hSlider; int dxP = 0; QFont fEdges("Courier", 9); int max_nO = 1; for (auto&& page : pages) { scene->addRect(cmpo(5), cmpo(5), cmpo(210-5), cmpo(297-5))->setPos(cmpo(dxP), 0); for (auto&& piece : page.pieces) { std::vector<sedge> pedges; TitleItem *tit = new TitleItem(QString::number(piece.id+1), this); tit->setRotation(piece.a); tit->setData(0, 123); scene->addItem(tit); bool hasLabel = false; QVector2D cTIT; for (auto&& fn : piece.faceId) { Triangle2d tt = cmpo(facettes[fn].triangle + piece.O + QVector2D(dxP+5, 5)); if (!hasLabel){ QVector2D b = QVector2D(tit->boundingRect().width(), tit->boundingRect().height()) / 2; cTIT = tt.centroid() - b; tit->setPos(cTIT.x(), cTIT.y()); hasLabel = true; } for (int i = 0; i < 3 ; i++){ // facette's edges and neighbors # int nF = facettes[fn].neighbors[i].nF; bool ok = true; QVector2D p1 = tt.point(i) - cTIT, p2 = tt.point(next(i)) - cTIT; for (auto&& e: pedges) { if (fn == e.nF && nF == e.fid) if ((eq(e.p1, p1) && eq(e.p2, p2)) || (eq(e.p1, p2) && eq(e.p2, p1))) { e.nb++; ok = false; break; } } if (ok) { sedge edge; edge.p1 = p1; edge.p2 = p2; edge.fid = fn; edge.nid = i; edge.nF = nF; edge.nb = 1; pedges.push_back(edge); } } } for (auto&& e : pedges) { if (e.nb == 1) { Edge* ed = edgeGet(e.fid, e.nF); if (ed->nO == -1) ed->nO = max_nO++; } LineItem *li = new LineItem(); li->setLine(e.p1.x(), e.p1.y(), e.p2.x(), e.p2.y()); int cop = facettes[e.fid].findNeighbor(e.nF)->cop; if (e.nb == 1) { li->setTypeLigne(cop < 0 ? TL_COUPE_V : (cop > 0) ? TL_COUPE_M : TL_COUPE_C); li->setOutlineColor(Qt::red); li->setOutlineWidth(2); li->setCustomPen(); li->setCursor(QCursor(Qt::SizeHorCursor)); li->setData(0, 1); li->setData(1, e.fid); li->setData(2, e.nF); QGraphicsSimpleTextItem *ti = scene->addSimpleText(QString::number(edgeGet(e.nF, e.fid)->nO), fEdges); QVector2D b = QVector2D(ti->boundingRect().width()/2, ti->boundingRect().height()); ti->setTransformOriginPoint(b.x(), b.y()); double ra = angle(e.p1, e.p2) - std::numbers::pi; ti->setRotation(radToDeg(ra)); QVector2D c = middle(e.p1, e.p2) - b; ti->setPos(c.x(), c.y()); ti->setParentItem(tit); } else { li->setTypeLigne(cop < 0 ? TL_LIE_V : (cop > 0) ? TL_LIE_M : TL_LIE_C); li->setOutlineColor((cop < 0) ? Qt::green : (cop > 0) ? QColor(180,0,0) : QColor(240,240,240)); //Qt::lightGray); li->setOutlineWidth(1); li->setCustomPen(); li->setCursor(QCursor(Qt::SplitHCursor)); li->setData(0, -1); li->setData(1, e.fid); li->setData(2, e.nF); } li->setParentItem(tit); } } dxP += 210; } vue->setScene(scene); }
-
Then why not include the source information as part of your tile ? That way when you need them you can simply retrieve them from the object that was selected/moved/etc.
-
@SGaist Indeed I'm already doing it like that for rotation and translation. My problem is that when I click on a line I would like to do something (cut or stick) but I don't know how. You are right suggesting that I could use the Title Object to do that, as it has a pointer on my dataset. I was fixed on my first idea that was to emit a signal to the mainWindow but it's not necessary.
-
What do you mean by "stick" ?
-
@SGaist On my screenshot with 2 pieces 1 and 2, by sticking the two facing edges numbered 5, the two pieces can get together and form a new piece.
-
@SGaist I'm trying to use the title item to reach my dataset but I'm facing a problem. to get the handle to my dataset, I need to read a public member of the TitleItem class, but from a LineItem I can only reach to its parentItem that was stored using
store->addItem(),
so it is a QGraphicsItem. I tried to cast it with
TitleItem * ti = (TitleItem)parentItem();
but I get the error
invalid conversion from ‘QGraphicsItem*’ to ‘TitleItem*’ [-fpermissive]Do I need to also create a customized QGraphicsScene where I could add a TitleItem so that I can get it ? (Sorry, not only it is my first QT application but I'm also starting using C++ from C).
-
You are declaring a pointer and c-style cast to an object.
-
@SGaist Oups, I forgot the *, it works now. I'm really happy to use QT, it's a very neat tool and it's documentation, examples and tutorials are very good.
Now that I can change my dataset, my problem is that I then need to refresh the view and as I cannot use signals/slots from a QGraphicsItem, I'm wondering how I could do that.
-
And as you mentioned that I used c-style cast, I read C++ doc and learned about C++-style cast that I didn't knew. So what I need to use is static_cast and my code becomes
TitleItem * ti = static_cast<TitleItem*>(parentItem());
Well I think that this first publication of mine is now solved. Thank you.
I also learn that a post can only be edited 3600 seconds after it is submitted. -