英文:
How to make a tab-like or ribbon-like label on a QGraphicsView?
问题
A good way to create a ribbon-like label for displaying text in a QGraphicsView, which contains a QGraphicsScene, is to use a QGraphicsItem or QGraphicsWidget for the ribbon. You can position it at the bottom of the view by setting its coordinates accordingly. This will make it independent of scene transformations and appear to "float above" the scene.
你可以在QGraphicsView中使用一个QGraphicsItem或QGraphicsWidget来创建一个类似于丝带的标签,然后通过设置它的坐标位置在视图底部,从而使其与场景的变换独立,看起来就像"漂浮"在场景之上。
英文:
What would be a good way to create a ribbon-like label for displaying text in a QGraphicsView which contains a QGraphicsScene such that the ribbon "floats above" the scene? i.e. is independent of the translation and other transformations of the scene and remains fixed at the bottom of the view.
I want to implement such a ribbon as a sort of status line to indicate when the application is in a modal state, but don't know if it's possible to do easily. (If it's not I'll think of something else) I don't need code just a general idea of how to approach this.
答案1
得分: 0
以下是翻译好的部分:
"An easy way to do this is to override drawForeground
in a custom scene. The trick is that drawForeground
will be passed a QPainter
that is set up to draw in scene coordinates but we want to draw in coordinates relative to the widget rectangle of the view, to do this you can simply set the painter's transform to the identity matrix."
"Code below. I call the content rectangle of the view minus the area taken up by any scroll bars 'the client rectangle' (because this is what it would be called in Win32) beyond that this code assumes that the custom scene is in one and only one view and the scene has getters/setters for showing/hiding a ribbon called 'the status line'."
"以下是代码示例。我将视图的内容矩形减去任何滚动条占用的区域称为 '客户区矩形'(因为在 Win32 中通常这样称呼),除此之外,此代码假定自定义场景仅存在一个视图,并且场景具有用于显示/隐藏称为 '状态行' 的带的 getter/setter。"
// ...
QRect client_rectangle(const QGraphicsView* view) {
auto view_rect = view->contentsRect();
if (view->verticalScrollBar()->isVisible()) {
auto wd = view_rect.width();
view_rect.setWidth(wd - view->verticalScrollBar()->width());
}
if (view->horizontalScrollBar()->isVisible()) {
auto hgt = view_rect.height();
view_rect.setHeight(hgt - view->horizontalScrollBar()->height());
}
return view_rect;
}
// ...
void MyCustomGraphicsScene::drawForeground(QPainter* painter, const QRectF& rect) {
QGraphicsScene::drawForeground(painter, rect);
if (is_status_line_visible()) {
QGraphicsView* view = views().first();
if (!view) {
return;
}
painter->setTransform(QTransform());
auto view_rect = client_rectangle(view);
QRect ribbon_rect = {
view_rect.bottomLeft() - QPoint(0, 35),
QSize(view_rect.width(), 35)
};
painter->fillRect(ribbon_rect, Qt::yellow);
painter->setPen(Qt::black);
painter->drawText(ribbon_rect, Qt::AlignRight | Qt::AlignVCenter, status_line_);
painter->resetTransform();
}
}
请注意,以上是原文的翻译。
英文:
An easy way to do this is to override drawForeground
in a custom scene. The trick is that drawForeground
will be passed a QPainter
that is set up to draw in scene coordinates but we want to draw in coordinates relative to the widget rectangle of the view, to do this you can simply set the painter's transform to the identity matrix.
Code below. I call the content rectangle of the view minus the area taken up by any scroll bars "the client rectangle" (because this is what it would be called in Win32) beyond that this code assumes that the custom scene is in one and only one view and the scene has getters/setters for showing/hiding a ribbon called "the status line".
<!-- language: C++ -->
// ...
QRect client_rectangle(const QGraphicsView* view) {
auto view_rect = view->contentsRect();
if (view->verticalScrollBar()->isVisible()) {
auto wd = view_rect.width();
view_rect.setWidth(wd - view->verticalScrollBar()->width());
}
if (view->horizontalScrollBar()->isVisible()) {
auto hgt = view_rect.height();
view_rect.setHeight(hgt - view->horizontalScrollBar()->height());
}
return view_rect;
}
// ...
void MyCustomGraphicsScene::drawForeground(QPainter* painter, const QRectF& rect) {
QGraphicsScene::drawForeground(painter, rect);
if (is_status_line_visible()) {
QGraphicsView* view = views().first();
if (!view) {
return;
}
painter->setTransform(QTransform());
auto view_rect = client_rectangle(view);
QRect ribbon_rect = {
view_rect.bottomLeft() - QPoint(0, 35),
QSize(view_rect.width(), 35)
};
painter->fillRect(ribbon_rect, Qt::yellow);
painter->setPen(Qt::black);
painter->drawText(ribbon_rect, Qt::AlignRight | Qt::AlignVCenter, status_line_);
painter->resetTransform();
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论