Skip to content

Conversation

@pizofreude
Copy link

Description

Fixes rightmost tick labels being clipped when using PlotItem with content margins.

Resolves issue #3375

Changes Made

Bug Fixes

  • AxisItem: Improved default settings for better label visibility
    • Changed hideOverlappingLabels=False for horizontal axes
    • Set autoReduceTextSpace=False for better text preservation
    • Enhanced text space calculation with parent margin awareness
  • PlotItem: Added layout expansion support for axis text overflow
    • Automatic margin expansion when axis labels need more space
    • Cross-layout communication between AxisItem and PlotItem

Testing

  • Added comprehensive test coverage in test_AxisItem.py
  • 5 new test functions covering defaults, methods, integration, and compatibility
  • All existing tests continue to pass (27 AxisItem tests total)

Backward Compatibility

  • Zero breaking changes to existing API
  • Manual settings still override improved defaults
  • Existing workarounds continue to work
  • Progressive enhancement approach

Technical Details

  • Enhanced AxisItem with 4 new private methods for text space management
  • Added PlotItem layout expansion methods with Qt version compatibility
  • Robust error handling prevents crashes in edge cases
  • Works across different Qt versions and data ranges

This commit resolves GitHub issue pyqtgraph#3375 where rightmost tick labels
were being clipped when using PlotItem with content margins.

Changes include:
- Improved default axis settings (hideOverlappingLabels=False for horizontal axes)
- Enhanced text space calculation methods in AxisItem
- Added PlotItem layout expansion support for axis text overflow
- Cross-platform compatibility for different Qt layout APIs
- Comprehensive error handling and backward compatibility

The fix ensures autoExpandTextSpace works properly with content margins
while maintaining full backward compatibility.
- Added test_AxisItem_clipping_fix_defaults() to verify improved defaults
- Added test_AxisItem_text_space_methods() to test new text space calculation methods
- Added test_AxisItem_clipping_with_plot_margins() to test the original issue scenario
- Added test_AxisItem_manual_settings_override() to ensure backward compatibility
- Added test_AxisItem_orientation_specific_behavior() to test all axis orientations
- All tests integrated into existing tests/graphicsItems/test_AxisItem.py
- All 27 tests passing including 5 new axis clipping tests
- Removed test_axis_clipping.py, test_axis_clipping_fix.py, test_fix_directly.py, validate_github_issue_fix.py
- All test functionality has been properly integrated into tests/graphicsItems/test_AxisItem.py
- Keeps repository clean and follows project test organization conventions
- Does not follow project conventions for documenting changes
- CHANGELOG is the established format for tracking changes
- Fix details should be in pull request description instead
- Keeps repository clean and follows project standards
if margins:
return margins
parent = parent.parentItem()
except (AttributeError, RuntimeError):

Check notice

Code scanning / CodeQL

Empty except Note

'except' clause does nothing but pass and there is no explanatory comment.
self._directLayoutExpansion(parent, required_space)
break
parent = parent.parentItem()
except (AttributeError, RuntimeError):

Check notice

Code scanning / CodeQL

Empty except Note

'except' clause does nothing but pass and there is no explanatory comment.
current_margins.bottom()
)

except (AttributeError, TypeError):

Check notice

Code scanning / CodeQL

Empty except Note

'except' clause does nothing but pass and there is no explanatory comment.
axis = self.axes[axis_name]['item']
if axis and hasattr(axis, '_onParentMarginsChanged'):
axis._onParentMarginsChanged(new_margins)
except (AttributeError, KeyError, RuntimeError):

Check notice

Code scanning / CodeQL

Empty except Note

'except' clause does nothing but pass and there is no explanatory comment.

# Notify axes of the change for better text space handling
self._notifyAxesOfMarginChange()
except (AttributeError, RuntimeError):

Check notice

Code scanning / CodeQL

Empty except Note

'except' clause does nothing but pass and there is no explanatory comment.
hide_overlapping_labels = True
# For horizontal axes, allow text to extend to prevent clipping
# This addresses the issue where rightmost labels get clipped
hide_overlapping_labels = False ## Changed from True - allow extension
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest to leave hide_overlapping_labels unchanged. The justification for it being on for the horizontal axis is the following:
In the common application of an updating real-time chart, long timestamp labels move along the bottom axis. These have a tendency to stick out on the left and overlap the zero of the vertical axis. In a competition between the specific 0 label and an arbitrary timestamp, the 0 should take priority. That is not a strong reason, but enough to suggest not introducing a change in behavior.

A smart solution might want to distinguish between a side with potentially colliding axis labels ("left"), and a side where that is not the case ("right"), but I think we do not currently have the necessary functionality to either implement that in AxisItem, or to detect the best approach.

Until we find that smart solution to handle this automatically, the next step of progressive improvement might be to add more hints to the docs for how and why to manually set this flag?

'tickTextHeight': 18,
'autoExpandTextSpace': True, ## automatically expand text space if needed
'autoReduceTextSpace': True,
'autoReduceTextSpace': auto_reduce_text_space, ## improved default based on orientation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change makes sense to me, since the horizontal axis text space should not usually expand with label length, and therefore have less need to recover from temporary expansion.

Parameters:
left, top, right, bottom (float): Margin values in pixels
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have nothing to contribute to a discussion on how to best implement this...
But gaining more control over the label layout is an excellent addition.

extra_needed = required_space - current_width

# Calculate new right margin (conservative approach)
additional_margin = min(extra_needed * 0.3, 50) # Cap at 50px max
Copy link
Contributor

@NilsNemitz NilsNemitz Oct 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider making the magic numbers into adjustable parameters? Especially if this might end up in a release without much testing period on master, it might break some application layouts in unexpected ways. Having a tweakable parameter would help with damage control in that case.

We can keep them as undocumented additions until we have more experience with the outcome and the urgency to make them accessible. Maybe PlotItem should acquire an axesLayout dictionary for this purpose.

@NilsNemitz
Copy link
Contributor

Hi @pizofreude , hi @j9ac9k !

Regretfully, I do not have the time to dig into this PR properly, and I would not trust myself to override setContentMargins and maintain a working system. But I think I probably made the most recent changes in the function of AxisItem, so I thought I should comment on my understanding of intended functionality.

I also wanted to say that there is clearly room for improvement in how the labels function, and I am very happy to see someone work on that :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants