Scale level label correctly to small(er) fonts

Not sure what fixed it exactly, and I guess we didn't need any relative
DPI scaling factor after all. Using the 3px margin on the level label
seems to make it look nice for any font size (i think) as well.

Gonna need some cleanup after this one.
bar_select
Tyler Goodlet 2020-11-02 15:27:48 -05:00
parent 96f700a762
commit 119196f2ff
4 changed files with 60 additions and 99 deletions

View File

@ -136,7 +136,9 @@ class AxisLabel(pg.GraphicsObject):
self._dpifont = DpiAwareFont()
self._dpifont.configure_to_dpi(_font._screen)
if font_size is not None:
# print(f"SETTING FONT TO: {font_size}")
self._dpifont._set_qfont_px_size(font_size)
# self._font._fm = QtGui.QFontMetrics(self._font)
@ -155,7 +157,7 @@ class AxisLabel(pg.GraphicsObject):
def paint(self, p, option, widget):
# p.drawPicture(0, 0, self.pic)
p.setCompositionMode(QtGui.QPainter.CompositionMode_SourceOver)
# p.setCompositionMode(QtGui.QPainter.CompositionMode_SourceOver)
if self.label_str:
@ -174,13 +176,13 @@ class AxisLabel(pg.GraphicsObject):
p.drawText(self.rect, self.text_flags, self.label_str)
def boundingRect(self): # noqa
# if self.label_str:
# self._size_br_from_str(self.label_str)
# return self.rect
if self.label_str:
self._size_br_from_str(self.label_str)
return self.rect
# return QtCore.QRectF()
return QtCore.QRectF()
return self.rect or QtCore.QRectF()
# return self.rect or QtCore.QRectF()
def _size_br_from_str(self, value: str) -> None:
"""Do our best to render the bounding rect to a set margin
@ -193,7 +195,7 @@ class AxisLabel(pg.GraphicsObject):
# px_per_char = self._font._fm.averageCharWidth()
# br = br * 1.88
txt_h, txt_w = br.height(), br.width()
print(f'orig: {txt_h}')
# print(f'orig: {txt_h}')
# txt_h = (br.topLeft() - br.bottomRight()).y()
# txt_w = len(value) * px_per_char
# txt_w *= 1.88
@ -220,9 +222,6 @@ class AxisLabel(pg.GraphicsObject):
class XAxisLabel(AxisLabel):
_w_margin = 0
_h_margin = 0
text_flags = (
QtCore.Qt.TextDontClip
| QtCore.Qt.AlignCenter
@ -246,14 +245,15 @@ class XAxisLabel(AxisLabel):
self.label_str = timestrs[0]
width = self.boundingRect().width()
w = self.boundingRect().width()
self.setPos(QPointF(
abs_pos.x() - width / 2, # - offset,
0
abs_pos.x() - w / 2 - offset,
0,
))
class YAxisLabel(AxisLabel):
_h_margin = 3
text_flags = (
# QtCore.Qt.AlignLeft
@ -280,7 +280,7 @@ class YAxisLabel(AxisLabel):
h = br.height()
self.setPos(QPointF(
0,
abs_pos.y() - h / 2 #- offset
abs_pos.y() - h / 2 - offset
))
@ -310,22 +310,6 @@ class YSticky(YAxisLabel):
last,
)
# chart = self._chart
# a = chart._array
# fields = a.dtype.fields
# if fields and 'close' in fields:
# index, last = a[-1][['index', 'close']]
# else: # non-ohlc case
# index = len(a) - 1
# last = a[chart.name][-1]
# self.update_from_data(
# index,
# last,
# )
def update_from_data(
self,
index: int,

View File

@ -18,11 +18,11 @@ from ._graphics import (
CrossHair,
ContentsLabel,
BarItems,
h_line,
level_line,
)
from ._axes import YSticky
from ._style import (
configure_font_to_dpi,
_font,
hcolor,
CHART_MARGINS,
_xaxis_at,
@ -660,7 +660,7 @@ async def _async_main(
chart_app = widgets['main']
# attempt to configure DPI aware font size
configure_font_to_dpi(current_screen())
_font.configure_to_dpi(current_screen())
# from ._exec import get_screen
# screen = get_screen(chart_app.geometry().bottomRight())
@ -898,8 +898,8 @@ async def chart_from_fsp(
# graphics.curve.setFillLevel(50)
# add moveable over-[sold/bought] lines
chart.plotItem.addItem(h_line(30))
chart.plotItem.addItem(h_line(70))
level_line(chart, 30)
level_line(chart, 70)
chart._shm = shm
chart._set_yrange()

View File

@ -644,6 +644,9 @@ class BarItems(pg.GraphicsObject):
class LevelLabel(YSticky):
_w_margin = 3
_h_margin = 3
def update_label(
self,
abs_pos: QPointF, # scene coords
@ -653,17 +656,18 @@ class LevelLabel(YSticky):
# this is read inside ``.paint()``
self.label_str = '{data: ,.{digits}f}'.format(
digits=self.digits, data=data).replace(',', ' ')
digits=self.digits,
data=data
).replace(',', ' ')
self._size_br_from_str(self.label_str)
br = self.boundingRect()
w, h = br.height(), br.width()
h, w = br.height(), br.width()
self.setPos(QPointF(
# *2 why? wat..?
0 - w*2,
abs_pos.y(), # - h / 2 - offset
-w,
abs_pos.y() - offset
))
def size_hint(self) -> Tuple[None, None]:
@ -683,16 +687,12 @@ class LevelLine(pg.InfiniteLine):
def set_value(self, value: float) -> None:
self.label.update_from_data(0, self.value())
# def valueChanged(self) -> None:
# print('yooo')
# self.label.update_from_data(0, self.value())
def level_line(
chart: 'ChartPlogWidget', # noqa
level: float,
digits: int = 3,
# label_precision: int = 0,
digits: int = 1,
font_size: int = 4,
) -> LevelLine:
"""Convenience routine to add a styled horizontal line to a plot.
@ -703,11 +703,10 @@ def level_line(
# TODO: pass this from symbol data
digits=digits,
opacity=1,
font_size=4,
font_size=font_size,
bg_color='default',
)
label.update_from_data(0, level)
# label._size_br_from_str(
line = LevelLine(
label,
@ -719,7 +718,6 @@ def level_line(
# activate/draw label
line.setValue(level)
# line.show()
chart.plotItem.addItem(line)
return line

View File

@ -9,28 +9,6 @@ from ..log import get_logger
log = get_logger(__name__)
# def configure_font_to_dpi(screen: QtGui.QScreen):
# """Set an appropriately sized font size depending on the screen DPI.
# If we end up needing to generalize this more here there are resources
# listed in the script in ``snippets/qt_screen_info.py``.
# """
# dpi = screen.physicalDotsPerInch()
# font_size = round(_font_inches_we_like * dpi)
# log.info(
# f"\nscreen:{screen.name()} with DPI: {dpi}"
# f"\nbest font size is {font_size}\n"
# )
# global _font
# _font.setPixelSize(font_size)
# _font._fm = QtGui.QFontMetrics(_font)
# return _font
# chart-wide font
# font size 6px / 53 dpi (3x scaled down on 4k hidpi)
_font_inches_we_like = 6 / 53 # px / (px / inch) = inch
@ -45,9 +23,9 @@ class DpiAwareFont:
self._qfont = QtGui.QFont(name)
self._iwl = _font_inches_we_like
self._qfm = QtGui.QFontMetrics(self._qfont)
self._font_size = None
self._physical_dpi = None
self._screen = None
self._dpi_scalar = 1.
def _set_qfont_px_size(self, px_size: int) -> None:
# self._qfont = QtGui.Qfont(self.name)
@ -62,9 +40,6 @@ class DpiAwareFont:
def px_size(self):
return self._qfont.pixelSize()
# def set_px_size(self, size: int) -> None:
# pass
def configure_to_dpi(self, screen: QtGui.QScreen):
"""Set an appropriately sized font size depending on the screen DPI.
@ -79,11 +54,12 @@ class DpiAwareFont:
f"\nbest font size is {font_size}\n"
)
self._set_qfont_px_size(font_size)
self._font_size = font_size
self._physical_dpi = dpi
self._screen = screen
def boundingRect(self, value: str) -> QtCore.QRectF:
# print(f'boundingRect STRING: {value}')
screen = self._screen
if screen is None:
raise RuntimeError("You must call .configure_to_dpi() first!")
@ -93,31 +69,34 @@ class DpiAwareFont:
# XXX: for wtv absolutely fucked reason, the scaling only applies
# to everything when the current font size **is not** the size
# needed to get the original desired text height... :mindblow:
if self._font_size != 6:
# scalar = self._qfm.fontDpi() / self._physical_dpi
scalar = screen.logicalDotsPerInch() / screen.physicalDotsPerInch()
# scalar = 100 / screen.physicalDotsPerInch()
# assert 0
print(f'SCALAR {scalar}')
# if self.px_size != 6:
# # scalar = self._qfm.fontDpi() / self._physical_dpi
# # self._dpi_scalar = scalar = screen.logicalDotsPerInch() / screen.physicalDotsPerInch()
# # self._dpi_scalar = scalar = 96 / screen.physicalDotsPerInch()
# # # assert 0
# # print(f'SCALAR {scalar}')
# # w = min(self._qfm.averageCharWidth() * len(value), unscaled_br.width())
return QtCore.QRectF(
# unscaled_br.x(),
# unscaled_br.y(),
0,
0,
unscaled_br.width() * scalar,
unscaled_br.height() * scalar,
)
else:
return QtCore.QRectF(
# unscaled_br.x(),
# unscaled_br.y(),
0,
0,
unscaled_br.width(),
unscaled_br.height(),
)
# return QtCore.QRectF(
# # unscaled_br.x(),
# # unscaled_br.y(),
# 0,
# 0,
# # w * scalar,
# unscaled_br.width(), # * scalar,
# unscaled_br.height(),# * scalar,
# )
# else:
return QtCore.QRectF(
# unscaled_br.x(),
# unscaled_br.y(),
0,
0,
unscaled_br.width(),
unscaled_br.height(),
)
# use pixel size to be cross-resolution compatible?
_font = DpiAwareFont()