Skip to content

Selective Rendering Artifacts with Embedded Widgets #521

@dadadawin

Description

@dadadawin
  1. Trigger Conditions (Why only specific nodes are affected)

The rendering artifact does not occur universally across all nodes. It is only triggered when all three conditions are present:

Embedded QWidget via QGraphicsProxyWidget
The node contains a QGraphicsProxyWidget (e.g., composite UI such as multiple spinboxes, sliders, or custom forms) that spans a significant portion of the node width.
DeviceCoordinateCache enabled
The node’s QGraphicsItem::DeviceCoordinateCache is active on the NodeGraphicsObject.
Fractional zoom scaling
The view is zoomed to a non-integer scale factor (e.g., 0.85x, 1.15x, 1.2x), introducing sub-pixel transformations.

Nodes without embedded widgets typically do not exhibit visible issues, because any minor clipping affects both background and content uniformly, making the artifact visually indistinguishable.

  1. Observed Symptom: “Floating Widget Illusion”

When the issue occurs, the node exhibits a clear visual mismatch:

The node background and border appear truncated on the right side
The embedded QWidget remains fully rendered and correctly sized
The widget appears to “float” outside the node boundary, over the canvas background

This creates a strong visual inconsistency:

Background width is reduced (visually clipped)
Embedded UI retains correct geometry (not clipped)
Result: widget extends beyond the node’s apparent boundary

  1. Root Cause: Cache-Based Integer Bounding and Coordinate Desynchronization

The issue arises from the interaction between Qt’s caching system and floating-point coordinate mapping during scaling.

3.1 DeviceCoordinateCache rendering behavior

When DeviceCoordinateCache is enabled, Qt renders the item into an internal cached buffer (pixmap-like representation) for performance optimization.

During fractional zoom:

The effective bounding rectangle is computed in device coordinates
The final cached buffer size is rounded to integer pixel dimensions
Sub-pixel precision is lost during this step

As a result, small fractional widths (e.g., 410.6 px) may be truncated to 410 px, causing consistent clipping along one edge.

3.2 QGraphicsProxyWidget rendering path divergence

QGraphicsProxyWidget behaves differently:

It is rendered as a live child widget, not part of the cached pixmap
It uses independent layout and geometry calculations
It responds directly to floating-point scene transformations

3.3 Resulting mismatch

This creates a desynchronization:

Component Rendering path Behavior
Node background Cached (integer-rounded) Slightly clipped
Embedded widget Live rendering (float-accurate) Correct size/position

Hence the widget remains visually correct while its parent background is truncated.

  1. Reproduction Steps

To reliably reproduce the issue:

Create a node containing a QGraphicsProxyWidget
Example: a QFrame with multiple controls and fixed width (~300px)

Ensure caching is enabled:

setCacheMode(QGraphicsItem::DeviceCoordinateCache);
Place the node in the scene (preferably near screen edge for clarity)
Zoom the view gradually (mouse wheel or slider)
Focus on non-integer scales (e.g., 1.1x–1.3x range)
Observe:
Right edge of node background progressively clips
Embedded widget remains fully visible and aligned to scene coordinates

  1. Root Fix / Mitigation

The artifact is eliminated by disabling cache-based rendering for nodes containing embedded widgets.

Recommended fix:
// REMOVE:
setCacheMode(QGraphicsItem::DeviceCoordinateCache);

// REPLACE WITH:
setCacheMode(QGraphicsItem::NoCache);

  1. Summary for Maintainers

While DeviceCoordinateCache improves rendering performance in large scenes, it introduces sub-pixel clipping artifacts under fractional scaling, particularly when QGraphicsProxyWidget is involved.

Because proxy widgets bypass the cache pipeline and use live coordinate mapping, any mismatch between cached and non-cached rendering paths becomes visually exposed.

Recommendation
Do not use DeviceCoordinateCache for nodes containing embedded widgets
Consider automatic cache disabling when QGraphicsProxyWidget is present
Alternatively, switch to ItemCoordinateCache or NoCache in mixed-content nodes for visual correctness

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions