Skip to content

Commit 211bf8f

Browse files
committed
Improved new flat-style for QwtPlot widgets
1 parent b19fced commit 211bf8f

6 files changed

Lines changed: 138 additions & 126 deletions

File tree

qwt/plot.py

Lines changed: 98 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ class QwtPlot(QFrame, QwtPlotDict):
278278
legendDataChanged = Signal("PyQt_PyObject", "PyQt_PyObject")
279279

280280
# enum Axis
281-
validAxes = yLeft, yRight, xBottom, xTop = list(range(4))
282-
axisCnt = len(validAxes)
281+
AXES = yLeft, yRight, xBottom, xTop = list(range(4))
282+
axisCnt = len(AXES) # Not necessary but ensure compatibility with PyQwt
283283

284284
# enum LegendPosition
285285
LeftLegend, RightLegend, BottomLegend, TopLegend = list(range(4))
@@ -315,8 +315,6 @@ def __init__(self, *args):
315315
# title
316316
self.__data.titleLabel = QwtTextLabel(self)
317317
self.__data.titleLabel.setObjectName("QwtPlotTitle")
318-
self.__data.titleLabel.setFont(QFont(self.fontInfo().family(), 14,
319-
QFont.Bold))
320318
text = QwtText(title)
321319
text.setRenderFlags(Qt.AlignCenter|Qt.TextWordWrap)
322320
self.__data.titleLabel.setText(text)
@@ -340,6 +338,7 @@ def __init__(self, *args):
340338
self.__data.canvas.setObjectName("QwtPlotCanvas")
341339
self.__data.canvas.installEventFilter(self)
342340

341+
# plot style
343342
self.setFlatStyle(True)
344343

345344
self.setSizePolicy(QSizePolicy.MinimumExpanding,
@@ -366,10 +365,90 @@ def __del__(self):
366365
# self.__data.layout = None
367366
# self.deleteAxesData()
368367
# self.__data = None
368+
369+
def setFlatStyle(self, state):
370+
"""
371+
Set or reset the flatStyle option
372+
373+
If the flatStyle option is set, the plot will be
374+
rendered without any margin (scales, canvas, layout).
375+
376+
Enabling this option makes the plot look flat and compact.
377+
378+
The flatStyle option is set to True by default.
379+
380+
:param bool state: True or False.
381+
382+
.. seealso::
383+
384+
:py:meth:`flatStyle()`
385+
"""
386+
def make_font(family=None, size=None, delta_size=None, weight=None):
387+
finfo = self.fontInfo()
388+
family = finfo.family() if family is None else family
389+
weight = -1 if weight is None else weight
390+
size = size if delta_size is None else finfo.pointSize()+delta_size
391+
return QFont(family, size, weight)
392+
if state:
393+
# New PythonQwt-exclusive flat style
394+
plot_title_font = make_font(family="Helvetica", delta_size=4,
395+
weight=QFont.Bold)
396+
axis_title_font = make_font(family="Helvetica", delta_size=2,
397+
weight=QFont.Bold)
398+
axis_label_font = make_font(family="Helvetica", delta_size=0)
399+
tick_lighter_factors = (150, 125, 100)
400+
scale_margin = scale_spacing = 0
401+
canvas_frame_style = QFrame.NoFrame
402+
plot_layout_canvas_margin = plot_layout_spacing = 0
403+
ticks_color = Qt.darkGray
404+
labels_color = "#444444"
405+
else:
406+
# Old PyQwt / Qwt style
407+
plot_title_font = make_font(size=14, weight=QFont.Bold)
408+
axis_title_font = make_font(size=12, weight=QFont.Bold)
409+
axis_label_font = make_font(size=10)
410+
tick_lighter_factors = (100, 100, 100)
411+
scale_margin = scale_spacing = 2
412+
canvas_frame_style = QFrame.Panel|QFrame.Sunken
413+
plot_layout_canvas_margin = 4
414+
plot_layout_spacing = 5
415+
ticks_color = labels_color = Qt.black
416+
self.canvas().setFrameStyle(canvas_frame_style)
417+
self.plotLayout().setCanvasMargin(plot_layout_canvas_margin)
418+
self.plotLayout().setSpacing(plot_layout_spacing)
419+
palette = self.palette()
420+
palette.setColor(QPalette.WindowText, QColor(ticks_color))
421+
palette.setColor(QPalette.Text, QColor(labels_color))
422+
self.setPalette(palette)
423+
for axis_id in self.AXES:
424+
scale_widget = self.axisWidget(axis_id)
425+
scale_draw = self.axisScaleDraw(axis_id)
426+
scale_widget.setFont(axis_label_font)
427+
scale_widget.setMargin(scale_margin)
428+
scale_widget.setSpacing(scale_spacing)
429+
scale_title = scale_widget.title()
430+
scale_title.setFont(axis_title_font)
431+
scale_widget.setTitle(scale_title)
432+
for tick_type, factor in enumerate(tick_lighter_factors):
433+
scale_draw.setTickLighterFactor(tick_type, factor)
434+
plot_title = self.title()
435+
plot_title.setFont(plot_title_font)
436+
self.setTitle(plot_title)
437+
self.__data.flatStyle = state
438+
439+
def flatStyle(self):
440+
"""
441+
:return: True if the flatStyle option is set.
442+
443+
.. seealso::
369444
445+
:py:meth:`setFlatStyle()`
446+
"""
447+
return self.__data.flatStyle
448+
370449
def initAxesData(self):
371450
"""Initialize axes"""
372-
self.__axisData = [AxisData() for axisId in self.validAxes]
451+
self.__axisData = [AxisData() for axisId in self.AXES]
373452

374453
self.__axisData[self.yLeft].scaleWidget = \
375454
QwtScaleWidget(QwtScaleDraw.LeftScale, self)
@@ -388,21 +467,16 @@ def initAxesData(self):
388467
].scaleWidget.setObjectName("QwtPlotAxisXTop")
389468
self.__axisData[self.xBottom
390469
].scaleWidget.setObjectName("QwtPlotAxisXBottom")
391-
392-
fscl = QFont(self.fontInfo().family(), 10)
393-
fttl = QFont(self.fontInfo().family(), 12, QFont.Bold)
394470

395-
for axisId in self.validAxes:
471+
for axisId in self.AXES:
396472
d = self.__axisData[axisId]
397473

398474
d.scaleEngine = QwtLinearScaleEngine()
399475

400476
d.scaleWidget.setTransformation(d.scaleEngine.transformation())
401-
d.scaleWidget.setFont(fscl)
402477
d.scaleWidget.setMargin(2)
403478

404479
text = d.scaleWidget.title()
405-
text.setFont(fttl)
406480
d.scaleWidget.setTitle(text)
407481

408482
d.doAutoScale = True
@@ -420,7 +494,7 @@ def initAxesData(self):
420494

421495
def deleteAxesData(self):
422496
#XXX Is is really necessary in Python? (pure transcription of C++)
423-
for axisId in self.validAxes:
497+
for axisId in self.AXES:
424498
self.__axisData[axisId].scaleEngine = None
425499
self.__axisData[axisId] = None
426500

@@ -871,7 +945,7 @@ def updateAxes(self):
871945
:py:meth:`setAxisScaleDiv()`, :py:meth:`replot()`,
872946
:py:meth:`QwtPlotItem.boundingRect()`
873947
"""
874-
intv = [QwtInterval() for _i in self.validAxes]
948+
intv = [QwtInterval() for _i in self.AXES]
875949
itmList = self.itemList()
876950
for item in itmList:
877951
if not item.testItemAttribute(QwtPlotItem.AutoScale):
@@ -884,7 +958,7 @@ def updateAxes(self):
884958
intv[item.xAxis()] |= QwtInterval(rect.left(), rect.right())
885959
if rect.height() >= 0.:
886960
intv[item.yAxis()] |= QwtInterval(rect.top(), rect.bottom())
887-
for axisId in self.validAxes:
961+
for axisId in self.AXES:
888962
d = self.__axisData[axisId]
889963
minValue = d.minValue
890964
maxValue = d.maxValue
@@ -989,67 +1063,6 @@ def autoReplot(self):
9891063
"""
9901064
return self.__data.autoReplot
9911065

992-
def setFlatStyle(self, state):
993-
"""
994-
Set or reset the flatStyle option
995-
996-
If the flatStyle option is set, the plot will be
997-
rendered without any margin (scales, canvas, layout).
998-
999-
Enabling this option makes the plot look flat and compact.
1000-
1001-
The flatStyle option is set to True by default.
1002-
1003-
:param bool state: True or False.
1004-
1005-
.. seealso::
1006-
1007-
:py:meth:`flatStyle()`
1008-
"""
1009-
if state:
1010-
self.canvas().setFrameStyle(QFrame.NoFrame)
1011-
self.plotLayout().setCanvasMargin(0)
1012-
self.plotLayout().setSpacing(0)
1013-
palette = self.palette()
1014-
palette.setColor(QPalette.WindowText, QColor(Qt.darkGray))
1015-
palette.setColor(QPalette.Text, QColor("#444444"))
1016-
self.setPalette(palette)
1017-
for axis_id in self.validAxes:
1018-
self.axisWidget(axis_id).setMargin(0)
1019-
self.axisWidget(axis_id).setSpacing(0)
1020-
for tick_type, factor in ((QwtScaleDiv.MajorTick, 100),
1021-
(QwtScaleDiv.MediumTick, 125),
1022-
(QwtScaleDiv.MinorTick, 150)):
1023-
self.axisScaleDraw(axis_id).setTickLighterFactor(tick_type,
1024-
factor)
1025-
# self.axisWidget(axis_id).setBorderDist(0, 0)
1026-
else:
1027-
self.canvas().setFrameStyle(QFrame.Panel|QFrame.Sunken)
1028-
self.plotLayout().setCanvasMargin(4)
1029-
self.plotLayout().setSpacing(5)
1030-
palette = self.palette()
1031-
palette.setColor(QPalette.WindowText, QColor(Qt.black))
1032-
palette.setColor(QPalette.Text, QColor(Qt.black))
1033-
self.setPalette(palette)
1034-
for axis_id in self.validAxes:
1035-
self.axisWidget(axis_id).setMargin(2)
1036-
self.axisWidget(axis_id).setSpacing(2)
1037-
for tick_type in (QwtScaleDiv.MajorTick, QwtScaleDiv.MediumTick,
1038-
QwtScaleDiv.MinorTick):
1039-
self.axisScaleDraw(axis_id).setTickLighterFactor(tick_type,
1040-
100)
1041-
self.__data.flatStyle = state
1042-
1043-
def flatStyle(self):
1044-
"""
1045-
:return: True if the flatStyle option is set.
1046-
1047-
.. seealso::
1048-
1049-
:py:meth:`setFlatStyle()`
1050-
"""
1051-
return self.__data.flatStyle
1052-
10531066
def setTitle(self, title):
10541067
"""
10551068
Change the plot's title
@@ -1170,7 +1183,7 @@ def sizeHint(self):
11701183
:py:meth:`minimumSizeHint()`
11711184
"""
11721185
dw = dh = 0
1173-
for axisId in self.validAxes:
1186+
for axisId in self.AXES:
11741187
if self.axisEnabled(axisId):
11751188
niceDist = 40
11761189
scaleWidget = self.axisWidget(axisId)
@@ -1231,7 +1244,7 @@ def get_layout_state(self):
12311244
return (self.contentsRect(),
12321245
self.__data.titleLabel.text(), self.__data.footerLabel.text(),
12331246
[(self.axisEnabled(axisId), self.axisTitle(axisId).text())
1234-
for axisId in self.validAxes],
1247+
for axisId in self.AXES],
12351248
self.__data.legend)
12361249

12371250
def updateLayout(self):
@@ -1253,7 +1266,7 @@ def updateLayout(self):
12531266
titleRect = self.__data.layout.titleRect().toRect()
12541267
footerRect = self.__data.layout.footerRect().toRect()
12551268
scaleRect = [self.__data.layout.scaleRect(axisId).toRect()
1256-
for axisId in self.validAxes]
1269+
for axisId in self.AXES]
12571270
legendRect = self.__data.layout.legendRect().toRect()
12581271
canvasRect = self.__data.layout.canvasRect().toRect()
12591272

@@ -1271,7 +1284,7 @@ def updateLayout(self):
12711284
else:
12721285
self.__data.footerLabel.hide()
12731286

1274-
for axisId in self.validAxes:
1287+
for axisId in self.AXES:
12751288
scaleWidget = self.axisWidget(axisId)
12761289
if self.axisEnabled(axisId):
12771290
if scaleRect[axisId] != scaleWidget.geometry():
@@ -1347,12 +1360,12 @@ def updateCanvasMargins(self):
13471360
:py:meth:`getCanvasMarginsHint()`,
13481361
:py:meth:`QwtPlotItem.getCanvasMarginHint()`
13491362
"""
1350-
maps = [self.canvasMap(axisId) for axisId in self.validAxes]
1363+
maps = [self.canvasMap(axisId) for axisId in self.AXES]
13511364
margins = self.getCanvasMarginsHint(maps, self.canvas().contentsRect())
13521365

13531366
doUpdate = False
13541367

1355-
for axisId in self.validAxes:
1368+
for axisId in self.AXES:
13561369
if margins[axisId] >= 0.:
13571370
m = np.ceil(margins[axisId])
13581371
self.plotLayout().setCanvasMargin(m, axisId)
@@ -1378,7 +1391,7 @@ def drawCanvas(self, painter):
13781391
:py:meth:`getCanvasMarginsHint()`,
13791392
:py:meth:`QwtPlotItem.getCanvasMarginHint()`
13801393
"""
1381-
maps = [self.canvasMap(axisId) for axisId in self.validAxes]
1394+
maps = [self.canvasMap(axisId) for axisId in self.AXES]
13821395
self.drawItems(painter, self.__data.canvas.contentsRect(), maps)
13831396

13841397
def drawItems(self, painter, canvasRect, maps):
@@ -1485,12 +1498,12 @@ def canvasBackground(self):
14851498
"""
14861499
return self.canvas().palette().brush(QPalette.Normal, QPalette.Window)
14871500

1488-
def axisValid(self, axisId):
1501+
def axisValid(self, axis_id):
14891502
"""
1490-
:param int axisId: Axis
1503+
:param int axis_id: Axis
14911504
:return: True if the specified axis exists, otherwise False
14921505
"""
1493-
return axisId in QwtPlot.validAxes
1506+
return axis_id in QwtPlot.AXES
14941507

14951508
def insertLegend(self, legend, pos=None, ratio=-1):
14961509
"""

0 commit comments

Comments
 (0)