QGraphicsTextItem
上有QGraphicsScene
个对象。用户可以通过拖动角来缩放QGraphicsTextItem
个对象。 (我使用自定义“转换编辑器”来执行此操作。)用户还可以通过更改属性面板中的字体大小来更改QGraphicsTextItem
的大小。我想要做的是统一这些,以便当用户通过用鼠标拖动角落来缩放对象时,在幕后它实际上在计算“需要什么尺寸的字体才能使得到的对象适合目标尺寸并保持比例系数为1.0?“
我现在正在做的是使用QGraphicsItem::mouseMoveEvent
让对象正常缩放,然后在鼠标缩放完成后在FinalizeMapScale
中触发QGraphicsItem::mouseReleaseEvent
方法。然后,此方法应将字体更改为适当的大小,并将比例设置回1.0。
我有一个似乎有效的解决方案,但我并不为此感到疯狂。我对Qt和C ++都比较陌生,所以对任何评论或更正都会很感激。
请在下面提交您自己的首选解决方案,对我的回答发表评论。谢谢!
[编辑] 根据评论中的要求,以下是缩放代码的基础知识。我们实际上采用了不同的方向,因此不再使用此代码(以及下面的代码)。此代码位于mouseMoveEvent
方法中,如果在右下角的“热点”中单击鼠标,则先前在mousePressEvent
中将“scaling_”标志设置为true。请注意,此代码位于装饰器QGraphicsItem中,该装饰器包含指向正在缩放的目标的指针。这种抽象对于我们的项目是必要的,但对于大多数用途来说可能有点过分。
void TransformDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
...
if (scaling_) {
QGraphicsItem *target_item = target_->AsQGraphicsItem();
target_item->setTransformOriginPoint(0.0, 0.0);
QPointF origin_scene = mapToScene(target_item->transformOriginPoint());
QPointF scale_position_scene = mapToScene(event->pos());
qreal unscaled_width = target_item->boundingRect().width();
qreal scale_x = (scale_position_scene.x() - origin_scene.x()) / unscaled_width;
if (scale_x * unscaled_width < kMinimumSize) {
scale_x = kMinimumSize / unscaled_width;
}
target_item->setScale(scale_x);
} else {
QGraphicsObject::mouseMoveEvent(event);
}
}
答案 0 :(得分:1)
请不要关于loop-with-exit结构的神圣战争。我们很满意。
void MapTextElement::FinalizeMapScale() {
// scene_document_width is the width of the text document as it appears in
// the scene after scaling. After we are finished with this method, we want
// the document to be as close as possible to this width with a scale of 1.0.
qreal scene_document_width = document()->size().width() * scale();
QString text = toPlainText();
// Once the difference between scene_document_width and the calculated width
// is below this value, we accept the new font size.
const qreal acceptable_delta = 1.0;
// If the difference between scene_document_width and the calculated width is
// more than this value, we guess at the new font size by calculating a new
// scale factor. Once it is beneath this value, we creep up (or down) by tiny
// increments. Without this, we would sometimes incur long "back and forth"
// loops when using the scale factor.
const qreal creep_delta = 8.0;
const qreal creep_increment = 0.1;
QScopedPointer<QTextDocument> test_document(document()->clone());
QFont new_font = this->font();
qreal delta = 0.0;
// To prevent infinite loops, we store the font size values that we try.
// Because of the unpredictable (at least to me) relationship between font
// point size and rendering size, this was the only way I could get it to
// work reliably.
QList<qreal> attempted_font_sizes;
while (true) {
test_document->setDefaultFont(new_font);
delta = scene_document_width - test_document->size().width();
if (std::abs(delta) <= acceptable_delta ||
attempted_font_sizes.contains(new_font.pointSizeF())) {
break;
}
attempted_font_sizes.append(new_font.pointSizeF());
qreal new_font_size = 0.0;
if (std::abs(delta) <= creep_delta) {
new_font_size = delta > 0.0 ? new_font.pointSizeF() + creep_increment
: new_font.pointSizeF() - creep_increment;
} else {
new_font_size = new_font.pointSizeF()
* scene_document_width
/ test_document->size().width();
}
new_font.setPointSizeF(new_font_size);
}
this->setFont(new_font);
this->setScale(1.0);
}
答案 1 :(得分:0)
另一种解决问题的方法是:Qt缩放了字体,我需要向用户显示的有效字体大小(用户看起来是多少,而不是文本项中设置的字体大小)作为他们选择的新字体大小?这只是一种替代方案,您仍需要类似于您的计算。
我有类似的问题。我有一个文本项目,我希望是单位大小(一个像素大小)像我的其他单位图形项目(然后用户可以缩放它们。)需要设置什么字体(setPointSize)? (还有什么setTextWidth和什么setDocumentMargin?)这种设计的优点是你不需要处理与任何其他形状的图形项目的缩放不同的文本项目的缩放。 (但我还没有工作。)
此外,用户界面问题:如果用户更改字体大小,项目是否会更改大小?或者它是否保持相同的大小和文本换行不同,在文本的末尾留下或多或少的空白?当用户添加新文本时,字体大小是否会发生变化,因此所有文本都符合形状的大小,或者形状大小是否会增加以容纳更多文本?换句话说,它更像是流程图应用程序(其中形状大小是固定的,字体缩小),还是像文字处理器应用程序(字体大小不变,形状(页数)增长?