viewer: click to select an ROI, with live move and a hand cursor
Clicking a box/circle on the image now selects it (syncing the side-panel combobox) and grabs it for moving, with a closed-hand cursor during the drag. The move recomputes ROI statistics live rather than only on release, throttled to at most one in-flight recompute so the worker is not flooded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -466,35 +466,39 @@ void JFJochDiffractionImage::setSelectedROI(QString name) {
|
||||
}
|
||||
|
||||
bool JFJochDiffractionImage::roiEditPress(const QPointF &scenePos) {
|
||||
if (!image || selected_roi_.isEmpty())
|
||||
if (!image)
|
||||
return false;
|
||||
|
||||
const auto &rois = image->Dataset().experiment.ROI().GetROIDefinition();
|
||||
const std::string sel = selected_roi_.toStdString();
|
||||
|
||||
for (const auto &b : rois.boxes)
|
||||
if (b.GetName() == sel) {
|
||||
const QRectF r(QPointF(b.GetXMin(), b.GetYMin()), QPointF(b.GetXMax(), b.GetYMax()));
|
||||
if (!r.contains(scenePos))
|
||||
return false;
|
||||
// Pick the first box/circle under the cursor, so an ROI can be grabbed by clicking it.
|
||||
for (const auto &b : rois.boxes) {
|
||||
const QRectF r(QPointF(b.GetXMin(), b.GetYMin()), QPointF(b.GetXMax(), b.GetYMax()));
|
||||
if (r.contains(scenePos)) {
|
||||
roi_edit_ = RoiEdit::MoveBox;
|
||||
edit_name_ = selected_roi_;
|
||||
edit_name_ = QString::fromStdString(b.GetName());
|
||||
edit_box_ = r;
|
||||
move_last_ = scenePos;
|
||||
selected_roi_ = edit_name_;
|
||||
emit roiSelected(edit_name_);
|
||||
setCursor(Qt::ClosedHandCursor);
|
||||
return true;
|
||||
}
|
||||
for (const auto &c : rois.circles)
|
||||
if (c.GetName() == sel) {
|
||||
const QPointF center(c.GetX(), c.GetY());
|
||||
if (QLineF(center, scenePos).length() > c.GetRadius_pxl())
|
||||
return false;
|
||||
}
|
||||
for (const auto &c : rois.circles) {
|
||||
const QPointF center(c.GetX(), c.GetY());
|
||||
if (QLineF(center, scenePos).length() <= c.GetRadius_pxl()) {
|
||||
roi_edit_ = RoiEdit::MoveCircle;
|
||||
edit_name_ = selected_roi_;
|
||||
edit_name_ = QString::fromStdString(c.GetName());
|
||||
edit_center_ = center;
|
||||
edit_radius_ = c.GetRadius_pxl();
|
||||
move_last_ = scenePos;
|
||||
selected_roi_ = edit_name_;
|
||||
emit roiSelected(edit_name_);
|
||||
setCursor(Qt::ClosedHandCursor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // azimuthal editing is not yet supported
|
||||
}
|
||||
|
||||
@@ -506,15 +510,28 @@ void JFJochDiffractionImage::roiEditMove(const QPointF &scenePos) {
|
||||
else if (roi_edit_ == RoiEdit::MoveCircle)
|
||||
edit_center_ += delta;
|
||||
updateOverlay();
|
||||
|
||||
// Live recompute, but keep at most one in flight (cleared in loadImage) so the
|
||||
// worker is not flooded with edits faster than it can recompute them.
|
||||
if (!live_pending_) {
|
||||
live_pending_ = true;
|
||||
emit roiGeometryEdited(BuildEditedROIDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
void JFJochDiffractionImage::roiEditRelease() {
|
||||
if (roi_edit_ == RoiEdit::None || !image) {
|
||||
roi_edit_ = RoiEdit::None;
|
||||
if (roi_edit_ == RoiEdit::None)
|
||||
return;
|
||||
}
|
||||
const ROIDefinition rois = BuildEditedROIDefinition();
|
||||
roi_edit_ = RoiEdit::None;
|
||||
setCursor(Qt::ArrowCursor);
|
||||
emit roiGeometryEdited(rois); // final, exact position
|
||||
}
|
||||
|
||||
ROIDefinition rois = image->Dataset().experiment.ROI().GetROIDefinition();
|
||||
ROIDefinition JFJochDiffractionImage::BuildEditedROIDefinition() const {
|
||||
ROIDefinition rois;
|
||||
if (image)
|
||||
rois = image->Dataset().experiment.ROI().GetROIDefinition();
|
||||
const std::string sel = edit_name_.toStdString();
|
||||
if (roi_edit_ == RoiEdit::MoveBox) {
|
||||
for (auto &b : rois.boxes)
|
||||
@@ -530,8 +547,7 @@ void JFJochDiffractionImage::roiEditRelease() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
roi_edit_ = RoiEdit::None;
|
||||
emit roiGeometryEdited(rois);
|
||||
return rois;
|
||||
}
|
||||
|
||||
|
||||
@@ -556,6 +572,7 @@ void JFJochDiffractionImage::setHDRMode(bool input) {
|
||||
}
|
||||
|
||||
void JFJochDiffractionImage::loadImage(std::shared_ptr<const JFJochReaderImage> in_image) {
|
||||
live_pending_ = false; // a live ROI edit (if any) has now been recomputed
|
||||
if (in_image) {
|
||||
image = in_image;
|
||||
UpdateForeground();
|
||||
|
||||
Reference in New Issue
Block a user