Add updateable y-sticky label

its_happening
Tyler Goodlet 2020-08-30 12:27:41 -04:00
parent 6ce8d1147e
commit 649798a91f
1 changed files with 91 additions and 36 deletions

View File

@ -3,11 +3,12 @@ Chart axes graphics and behavior.
"""
import pyqtgraph as pg
from PyQt5 import QtCore, QtGui
from PyQt5.QtCore import QPointF
# from .quantdom.base import Quotes
from .quantdom.utils import fromtimestamp
from ._style import _font
from ._style import _font, hcolor
class PriceAxis(pg.AxisItem):
@ -18,7 +19,7 @@ class PriceAxis(pg.AxisItem):
) -> None:
super().__init__(orientation='right')
self.setStyle(**{
'textFillLimits': [(0, 1)],
'textFillLimits': [(0, 0.5)],
# 'tickTextWidth': 10,
# 'tickTextHeight': 25,
# 'autoExpandTextSpace': True,
@ -52,10 +53,11 @@ class DynamicDateAxis(pg.AxisItem):
# default styling
self.setStyle(
tickTextOffset=7,
textFillLimits=[(0, 0.90)],
textFillLimits=[(0, 0.70)],
# TODO: doesn't seem to work -> bug in pyqtgraph?
# tickTextHeight=2,
)
# self.setHeight(35)
def tickStrings(self, values, scale, spacing):
# if len(values) > 1 or not values:
@ -80,13 +82,13 @@ class DynamicDateAxis(pg.AxisItem):
class AxisLabel(pg.GraphicsObject):
# bg_color = pg.mkColor('#a9a9a9')
bg_color = pg.mkColor('#808080')
fg_color = pg.mkColor('#000000')
bg_color = pg.mkColor(hcolor('gray'))
fg_color = pg.mkColor(hcolor('black'))
def __init__(
self,
parent=None,
digits=0,
digits=1,
color=None,
opacity=1,
**kwargs
@ -96,33 +98,17 @@ class AxisLabel(pg.GraphicsObject):
self.opacity = opacity
self.label_str = ''
self.digits = digits
# self.quotes_count = len(Quotes) - 1
# some weird color convertion logic?
if isinstance(color, QtGui.QPen):
self.bg_color = color.color()
self.fg_color = pg.mkColor('#ffffff')
self.fg_color = pg.mkColor(hcolor('black'))
elif isinstance(color, list):
self.bg_color = {'>0': color[0].color(), '<0': color[1].color()}
self.fg_color = pg.mkColor('#ffffff')
self.fg_color = pg.mkColor(hcolor('white'))
self.setFlag(self.ItemIgnoresTransformations)
def tick_to_string(self, tick_pos):
raise NotImplementedError()
def boundingRect(self): # noqa
raise NotImplementedError()
def update_label(self, evt_post, point_view):
raise NotImplementedError()
def update_label_test(self, ypos=0, ydata=0):
self.label_str = self.tick_to_string(ydata)
height = self.boundingRect().height()
offset = 0 # if have margins
new_pos = QtCore.QPointF(0, ypos - height / 2 - offset)
self.setPos(new_pos)
def paint(self, p, option, widget):
p.setRenderHint(p.TextAntialiasing, True)
p.setPen(self.fg_color)
@ -141,12 +127,38 @@ class AxisLabel(pg.GraphicsObject):
p.drawText(option.rect, self.text_flags, self.label_str)
# uggggghhhh
def tick_to_string(self, tick_pos):
raise NotImplementedError()
def boundingRect(self): # noqa
raise NotImplementedError()
def update_label(self, evt_post, point_view):
raise NotImplementedError()
# end uggggghhhh
# _common_text_flags = (
# QtCore.Qt.TextDontClip |
# QtCore.Qt.AlignCenter |
# QtCore.Qt.AlignTop |
# QtCore.Qt.AlignHCenter |
# QtCore.Qt.AlignVCenter
# )
class XAxisLabel(AxisLabel):
text_flags = (
QtCore.Qt.TextDontClip | QtCore.Qt.AlignCenter | QtCore.Qt.AlignTop
QtCore.Qt.TextDontClip
| QtCore.Qt.AlignCenter
# | QtCore.Qt.AlignTop
| QtCore.Qt.AlignVCenter
# | QtCore.Qt.AlignHCenter
)
# text_flags = _common_text_flags
def tick_to_string(self, tick_pos):
# TODO: change to actual period
@ -157,34 +169,77 @@ class XAxisLabel(AxisLabel):
return fromtimestamp(bars[round(tick_pos)]['time']).strftime(tpl)
def boundingRect(self): # noqa
return QtCore.QRectF(0, 0, 145, 50)
return QtCore.QRectF(0, 0, 145, 40)
def update_label(self, evt_post, point_view):
ibar = point_view.x()
def update_label(self, abs_pos, data):
# ibar = view_pos.x()
# if ibar > self.quotes_count:
# return
self.label_str = self.tick_to_string(ibar)
self.label_str = self.tick_to_string(data)
width = self.boundingRect().width()
offset = 0 # if have margins
new_pos = QtCore.QPointF(evt_post.x() - width / 2 - offset, 0)
new_pos = QPointF(abs_pos.x() - width / 2 - offset, 0)
self.setPos(new_pos)
class YAxisLabel(AxisLabel):
# text_flags = _common_text_flags
text_flags = (
QtCore.Qt.TextDontClip | QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter
QtCore.Qt.AlignLeft
| QtCore.Qt.TextDontClip
| QtCore.Qt.AlignVCenter
)
def tick_to_string(self, tick_pos):
# WTF IS THIS FORMAT?
return ('{: ,.%df}' % self.digits).format(tick_pos).replace(',', ' ')
def boundingRect(self): # noqa
return QtCore.QRectF(0, 0, 100, 40)
return QtCore.QRectF(0, 0, 120, 30)
def update_label(self, evt_post, point_view):
self.label_str = self.tick_to_string(point_view.y())
def update_label(
self,
abs_pos: QPointF, # scene coords
data: float, # data for text
) -> None:
self.label_str = self.tick_to_string(data)
height = self.boundingRect().height()
offset = 0 # if have margins
new_pos = QtCore.QPointF(0, evt_post.y() - height / 2 - offset)
new_pos = QPointF(0, abs_pos.y() - height / 2 - offset)
self.setPos(new_pos)
class YSticky(YAxisLabel):
"""Y-axis label that sticks to where it's placed despite chart resizing.
"""
def __init__(
self,
chart,
*args,
**kwargs
) -> None:
super().__init__(*args, **kwargs)
self._chart = chart
# XXX: not sure why this wouldn't work with a proxy?
# pg.SignalProxy(
# delay=0,
# rateLimit=60,
# slot=last.update_on_resize,
# )
chart.sigRangeChanged.connect(self.update_on_resize)
def update_on_resize(self, vr, r):
# TODO: figure out how to generalize across data schema
self.update_from_data(*self._chart._array[-1][['index', 'close']])
def update_from_data(
self,
index: int,
last: float,
) -> None:
self.update_label(
self._chart.mapFromView(QPointF(index, last)),
last
)