Viewer: paint the resolution readout in drawForeground, not as a scene item
The hovered "d = ... A" readout was a QGraphicsTextItem flagged ItemIgnoresTransformations, repositioned on every mouse motion. Qt cannot compute a tight dirty rect for an item that ignores the view transform, so it marks the entire viewport dirty whenever such an item moves or changes text -- and this one moved constantly. Paint it in drawForeground() in viewport pixels instead, and repaint only the union of its old and new rectangles. That also removes the item lifetime special-casing: it was deliberately kept out of overlay_items_, had to be nulled by hand after scene()->clear(), and carried comments in three places warning about the dangling pointer. This does not reduce raw X11 traffic -- there every repaint uploads the whole window whatever the damage -- but it cuts the work per hover, and it does matter under a compressing remote protocol (VNC/NX/xpra), which encodes only the region that actually changed. Verified against the previous build: same text, colour and position. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -449,8 +449,6 @@ void JFJochDiffractionImage::addCustomOverlay() {
|
||||
DrawPredictions();
|
||||
if (show_saturation)
|
||||
DrawSaturation();
|
||||
|
||||
DrawResolutionText();
|
||||
}
|
||||
|
||||
void JFJochDiffractionImage::DrawROIs() {
|
||||
@@ -916,7 +914,7 @@ void JFJochDiffractionImage::loadImage(std::shared_ptr<const JFJochReaderImage>
|
||||
scene()->clear();
|
||||
resetScenePointers();
|
||||
hover_resolution = NAN;
|
||||
hover_resolution_item = nullptr;
|
||||
DrawResolutionText();
|
||||
|
||||
CalcROI();
|
||||
}
|
||||
@@ -1000,57 +998,56 @@ void JFJochDiffractionImage::setResolutionRingMode(RingMode mode) {
|
||||
updateOverlay();
|
||||
}
|
||||
|
||||
void JFJochDiffractionImage::DrawResolutionText() {
|
||||
auto scn = scene();
|
||||
if (!scn) {
|
||||
hover_resolution_item = nullptr; // scene gone
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide item if no valid hover resolution
|
||||
if (!image || !std::isfinite(hover_resolution) || hover_resolution <= 0.0f) {
|
||||
if (hover_resolution_item)
|
||||
hover_resolution_item->setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const QRectF visibleRect = mapToScene(viewport()->geometry()).boundingRect();
|
||||
|
||||
// Fixed on-screen font size (no dependence on scale_factor)
|
||||
static QFont HoverResolutionFont() {
|
||||
QFont font("Arial");
|
||||
font.setPixelSize(32); // big, constant size on screen
|
||||
font.setPixelSize(32); // big, constant size on screen
|
||||
return font;
|
||||
}
|
||||
|
||||
const QString label =
|
||||
QString("d = %1 Å").arg(QString::number(hover_resolution, 'f', 2));
|
||||
QString JFJochDiffractionImage::HoverResolutionLabel() const {
|
||||
if (!image || !std::isfinite(hover_resolution) || hover_resolution <= 0.0f)
|
||||
return {};
|
||||
return QString("d = %1 \u00C5").arg(QString::number(hover_resolution, 'f', 2));
|
||||
}
|
||||
|
||||
// Create the item if it does not exist yet; otherwise reuse it
|
||||
// NOTE: hover_resolution_item is NOT tracked in overlay_items_ — it is persistent
|
||||
if (!hover_resolution_item) {
|
||||
hover_resolution_item = scn->addText(label, font);
|
||||
hover_resolution_item->setZValue(10.0);
|
||||
// Make the text ignore zooming / view transforms
|
||||
hover_resolution_item->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
|
||||
} else {
|
||||
hover_resolution_item->setFont(font);
|
||||
hover_resolution_item->setPlainText(label);
|
||||
void JFJochDiffractionImage::drawForeground(QPainter *painter, const QRectF &rect) {
|
||||
JFJochImage::drawForeground(painter, rect);
|
||||
|
||||
const QString label = HoverResolutionLabel();
|
||||
if (label.isEmpty())
|
||||
return;
|
||||
|
||||
painter->save();
|
||||
painter->resetTransform(); // lay the readout out in viewport pixels, not scene units
|
||||
painter->setFont(HoverResolutionFont());
|
||||
painter->setPen(feature_color);
|
||||
painter->drawText(hover_text_rect_, Qt::AlignLeft | Qt::AlignTop, label);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void JFJochDiffractionImage::DrawResolutionText() {
|
||||
const QRect previous = hover_text_rect_;
|
||||
const QString label = HoverResolutionLabel();
|
||||
|
||||
if (label.isEmpty())
|
||||
hover_text_rect_ = QRect();
|
||||
else {
|
||||
constexpr int margin_px = 10;
|
||||
const QFontMetrics fm(HoverResolutionFont());
|
||||
hover_text_rect_ = QRect(QPoint(margin_px, margin_px), fm.size(0, label));
|
||||
}
|
||||
|
||||
hover_resolution_item->setDefaultTextColor(feature_color);
|
||||
|
||||
// Keep a roughly constant ~10 px margin by compensating with scale_factor
|
||||
const qreal margin_px = 10.0;
|
||||
const qreal margin_scene = margin_px / std::max(0.0001, scale_factor);
|
||||
|
||||
QPointF topLeft(visibleRect.left() + margin_scene,
|
||||
visibleRect.top() + margin_scene);
|
||||
hover_resolution_item->setPos(topLeft);
|
||||
hover_resolution_item->setVisible(true);
|
||||
// Repaint just the readout. The previous version was a QGraphicsItem flagged
|
||||
// ItemIgnoresTransformations, which makes Qt mark the whole viewport dirty every time the
|
||||
// item moves or its text changes - and it moved on every mouse motion.
|
||||
const QRect dirty = previous.united(hover_text_rect_).adjusted(-2, -2, 2, 2);
|
||||
if (!dirty.isEmpty())
|
||||
viewport()->update(dirty);
|
||||
}
|
||||
|
||||
void JFJochDiffractionImage::beforeOverlayCleared() {
|
||||
// hover_resolution_item is NOT in overlay_items_, so the selective clear won't touch it.
|
||||
// However, if scene()->clear() is ever called (e.g. on loadImage(nullptr)),
|
||||
// the caller must also set hover_resolution_item = nullptr separately.
|
||||
// The resolution readout is painted in drawForeground(), not held as a scene item, so
|
||||
// clearing the overlay (or the whole scene) cannot leave a dangling pointer behind.
|
||||
}
|
||||
|
||||
void JFJochDiffractionImage::leaveEvent(QEvent *event) {
|
||||
|
||||
Reference in New Issue
Block a user