From f1e966a7d031bca04f37403d551f4aed74f05df3 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Mon, 8 Dec 2025 15:40:35 +0100 Subject: [PATCH] jfjoch_viewer: Display resolution in top left corner --- .../image_viewer/JFJochDiffractionImage.cpp | 79 ++++++++++++++++++- viewer/image_viewer/JFJochDiffractionImage.h | 6 ++ viewer/image_viewer/JFJochImage.cpp | 4 + viewer/image_viewer/JFJochImage.h | 2 + 4 files changed, 90 insertions(+), 1 deletion(-) diff --git a/viewer/image_viewer/JFJochDiffractionImage.cpp b/viewer/image_viewer/JFJochDiffractionImage.cpp index 205069f9..5d040d1d 100644 --- a/viewer/image_viewer/JFJochDiffractionImage.cpp +++ b/viewer/image_viewer/JFJochDiffractionImage.cpp @@ -43,11 +43,22 @@ void JFJochDiffractionImage::mouseHover(QMouseEvent *event) { .arg(coord.y(), 0, 'f', 1) .arg(intensity_str) .arg(res, 0, 'f', 2)); - } else + + // Update hovered resolution text without rebuilding the whole overlay + hover_resolution = res; + DrawResolutionText(); + } else { emit writeStatusBar(""); + // Clear hover resolution text when outside image + if (std::isfinite(hover_resolution)) { + hover_resolution = NAN; + DrawResolutionText(); + } + } } + void JFJochDiffractionImage::LoadImageInternal() { if (!image) return; @@ -298,6 +309,8 @@ void JFJochDiffractionImage::addCustomOverlay() { DrawPredictions(); if (show_saturation) DrawSaturation(); + + DrawResolutionText(); } void JFJochDiffractionImage::loadImage(std::shared_ptr in_image) { @@ -316,6 +329,9 @@ void JFJochDiffractionImage::loadImage(std::shared_ptr W = 0; H = 0; if (scene()) scene()->clear(); + hover_resolution = NAN; + hover_resolution_item = nullptr; + CalcROI(); } } @@ -403,3 +419,64 @@ void JFJochDiffractionImage::setResolutionRingMode(RingMode mode) { ring_mode = 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) + QFont font("Arial"); + font.setPixelSize(32); // big, constant size on screen + + const QString label = + QString("d = %1 Å").arg(QString::number(hover_resolution, 'f', 2)); + + // Create the item if it does not exist yet; otherwise reuse it + 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); + } + + 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); +} + +void JFJochDiffractionImage::beforeOverlayCleared() { + // The scene is about to clear (and delete) all its items. + // Drop our non-owning pointer so we never touch a deleted item. + hover_resolution_item = nullptr; +} + +void JFJochDiffractionImage::leaveEvent(QEvent *event) { + // Mouse left the view: clear hover resolution and hide text + if (std::isfinite(hover_resolution)) { + hover_resolution = NAN; + DrawResolutionText(); + } + JFJochImage::leaveEvent(event); +} diff --git a/viewer/image_viewer/JFJochDiffractionImage.h b/viewer/image_viewer/JFJochDiffractionImage.h index 2d5a86a4..a06c35a7 100644 --- a/viewer/image_viewer/JFJochDiffractionImage.h +++ b/viewer/image_viewer/JFJochDiffractionImage.h @@ -13,6 +13,8 @@ Q_OBJECT QColor prediction_color = Qt::darkRed; QColor ice_ring_color = Qt::cyan; + float hover_resolution = NAN; + QGraphicsTextItem* hover_resolution_item = nullptr; // big text in top-left public: enum class RingMode {Auto, Estimation, Manual, None, IceRings}; Q_ENUM(RingMode) @@ -28,8 +30,12 @@ private: void DrawBeamCenter(); void DrawTopPixels(); void DrawSaturation(); + void DrawResolutionText(); void DrawCross(float x, float y, float size, float width, float z = 1); + void beforeOverlayCleared() override; + void leaveEvent(QEvent *event) override; + std::shared_ptr image; int32_t show_highest_pixels = 0; diff --git a/viewer/image_viewer/JFJochImage.cpp b/viewer/image_viewer/JFJochImage.cpp index 2c9f1246..c433d5ef 100644 --- a/viewer/image_viewer/JFJochImage.cpp +++ b/viewer/image_viewer/JFJochImage.cpp @@ -681,6 +681,8 @@ void JFJochImage::writePixelLabels() { void JFJochImage::updateOverlay() { if (!scene() || W * H <= 0) return; + beforeOverlayCleared(); + scene()->clear(); scene()->addItem(new QGraphicsPixmapItem(pixmap)); @@ -828,3 +830,5 @@ void JFJochImage::fitToViewShorterSideOnce() { void JFJochImage::adjustForeground(bool input) { m_adjustForegroundWithWheel = input; } + +void JFJochImage::beforeOverlayCleared() {} diff --git a/viewer/image_viewer/JFJochImage.h b/viewer/image_viewer/JFJochImage.h index 8e3bd522..ff399a0d 100644 --- a/viewer/image_viewer/JFJochImage.h +++ b/viewer/image_viewer/JFJochImage.h @@ -30,6 +30,8 @@ class JFJochImage : public QGraphicsView { ROIMessage accumulateROI(int64_t xmin, int64_t xmax, int64_t ymin, int64_t ymax, const std::function& inside); protected: + virtual void beforeOverlayCleared(); + bool show_saturation = false; bool auto_bg = false;