3131 Qt ,
3232 qFuzzyCompare ,
3333)
34- from qtpy .QtGui import QFontMetrics , QPalette , QTransform
34+ from qtpy .QtGui import QFont , QFontMetrics , QPalette , QTransform
3535
3636from qwt ._math import qwtRadians
3737from qwt .scale_div import QwtScaleDiv
@@ -760,6 +760,15 @@ def labelPosition(self, value):
760760 :param float value: Value
761761 :return: Position, where to paint a label
762762 """
763+ # For backward compatibility, use a default font metrics approach
764+ # when rotation is involved
765+ if abs (self .labelRotation ()) > 1e-6 :
766+ # We need font information for proper rotation-aware positioning
767+ # Use QFontMetrics with a default font as fallback
768+ default_font = QFont ()
769+ return self ._labelPositionWithFont (default_font , value )
770+
771+ # Original implementation for non-rotated labels
763772 tval = self .scaleMap ().transform (value )
764773 dist = self .spacing ()
765774 if self .hasComponent (QwtAbstractScaleDraw .Backbone ):
@@ -784,6 +793,80 @@ def labelPosition(self, value):
784793
785794 return QPointF (px , py )
786795
796+ def _labelPositionWithFont (self , font , value ):
797+ """
798+ Find the position where to paint a label, taking rotation into account.
799+
800+ :param QFont font: Font used for the label
801+ :param float value: Value
802+ :return: Position where to paint a label
803+ """
804+ tval = self .scaleMap ().transform (value )
805+ dist = self .spacing ()
806+ if self .hasComponent (QwtAbstractScaleDraw .Backbone ):
807+ dist += max ([1 , self .penWidth ()])
808+ if self .hasComponent (QwtAbstractScaleDraw .Ticks ):
809+ dist += self .tickLength (QwtScaleDiv .MajorTick )
810+
811+ # Add rotation-aware offset
812+ dist += self ._rotatedLabelOffset (font , value )
813+
814+ px = 0
815+ py = 0
816+ if self .alignment () == self .RightScale :
817+ px = self .__data .pos .x () + dist
818+ py = tval
819+ elif self .alignment () == self .LeftScale :
820+ px = self .__data .pos .x () - dist
821+ py = tval
822+ elif self .alignment () == self .BottomScale :
823+ px = tval
824+ py = self .__data .pos .y () + dist
825+ elif self .alignment () == self .TopScale :
826+ px = tval
827+ py = self .__data .pos .y () - dist
828+
829+ return QPointF (px , py )
830+
831+ def _rotatedLabelOffset (self , font , value ):
832+ """
833+ Calculate the additional offset needed for a rotated label
834+ to avoid overlap with the scale backbone and ticks.
835+
836+ :param QFont font: Font used for the label
837+ :param float value: Value for which to calculate the offset
838+ :return: Additional offset distance
839+ """
840+ rotation = self .labelRotation ()
841+ if abs (rotation ) < 1e-6 : # No rotation, no additional offset needed
842+ return 0.0
843+
844+ lbl , labelSize = self .tickLabel (font , value )
845+ if lbl .isEmpty ():
846+ return 0.0
847+
848+ # Convert rotation to radians
849+ angle = qwtRadians (rotation )
850+ cos_a = abs (math .cos (angle ))
851+ sin_a = abs (math .sin (angle ))
852+
853+ # Calculate the rotated bounding box dimensions
854+ width = labelSize .width ()
855+ height = labelSize .height ()
856+ rotated_width = width * cos_a + height * sin_a
857+ rotated_height = width * sin_a + height * cos_a
858+
859+ # Calculate additional offset based on scale alignment
860+ additional_offset = 0.0
861+ if self .alignment () in (self .LeftScale , self .RightScale ):
862+ # For vertical scales, consider the horizontal extent of rotated label
863+ additional_offset = max (0 , (rotated_width - width ) * 0.5 )
864+ else : # TopScale, BottomScale
865+ # For horizontal scales, consider the vertical extent of rotated label
866+ additional_offset = max (0 , (rotated_height - height ) * 0.5 )
867+
868+ return additional_offset
869+
787870 def drawTick (self , painter , value , len_ ):
788871 """
789872 Draw a tick
@@ -957,7 +1040,7 @@ def drawLabel(self, painter, value):
9571040 lbl , labelSize = self .tickLabel (painter .font (), value )
9581041 if lbl is None or lbl .isEmpty ():
9591042 return
960- pos = self .labelPosition ( value )
1043+ pos = self ._labelPositionWithFont ( painter . font (), value )
9611044 transform = self .labelTransformation (pos , labelSize )
9621045 painter .save ()
9631046 painter .setWorldTransform (transform , True )
@@ -982,7 +1065,7 @@ def boundingLabelRect(self, font, value):
9821065 lbl , labelSize = self .tickLabel (font , value )
9831066 if lbl .isEmpty ():
9841067 return QRect ()
985- pos = self .labelPosition ( value )
1068+ pos = self ._labelPositionWithFont ( font , value )
9861069 transform = self .labelTransformation (pos , labelSize )
9871070 return transform .mapRect (QRect (QPoint (0 , 0 ), labelSize .toSize ()))
9881071
@@ -1038,7 +1121,7 @@ def labelRect(self, font, value):
10381121 lbl , labelSize = self .tickLabel (font , value )
10391122 if not lbl or lbl .isEmpty ():
10401123 return QRectF (0.0 , 0.0 , 0.0 , 0.0 )
1041- pos = self .labelPosition ( value )
1124+ pos = self ._labelPositionWithFont ( font , value )
10421125 transform = self .labelTransformation (pos , labelSize )
10431126 br = transform .mapRect (QRectF (QPointF (0 , 0 ), labelSize ))
10441127 br .translate (- pos .x (), - pos .y ())
0 commit comments