Custom color and padding for frame area outside visible plot area?

350 views
Skip to first unread message

JJ

unread,
May 21, 2019, 2:55:44 PM5/21/19
to pyqtgraph
By default the plot background color is black. However, this color extends into the area of the axis and padding between the plot area and window edges.
What I would like to do is change the color and padding of the plot frame area while leaving the plot area itself black or grey. How is this possible?




Patrick

unread,
May 22, 2019, 2:16:38 AM5/22/19
to pyqtgraph
Hi,

I think you want the setBackgroundColor method from ViewBox. So get the ViewBox associated with your PlotItem like:
plotItem.getViewBox().setBackgroundColor((192, 192, 192))

Patrick

JJ

unread,
May 22, 2019, 2:38:13 AM5/22/19
to pyqtgraph
Hi Patrick,
Thanks, this appears to work. However, the grid lines disappear. Do you have any idea on how to prevent the setting of the background color from drawing over the grid lines?

Patrick

unread,
May 22, 2019, 3:17:19 AM5/22/19
to pyqtgraph
Hi,

Yeah, I'm not sure if the z-orders are set correctly for everything. You'd think the background should be drawn behind the grid... Try something like:
 [ plotItem.getAxis(ax).setZValue(10) for ax in plotItem.axes ]
I think the grid lines are then over the top of the plot lines, you may need to play with the "10" if that's a problem. (Note this is the answer to getting grid lines over the top of an imageItem as well...)

Patrick

JJ

unread,
May 22, 2019, 10:14:12 AM5/22/19
to pyqtgraph
Hi Patrick,
I've adjusted the z values and it helps. Do you have any idea about how to adjust the padding of the viewbox?
John

Patrick

unread,
May 22, 2019, 8:27:18 PM5/22/19
to pyqtgraph
Hi,

Yeah, all that spacing/padding functionality is buried in the Qt QGraphicsWidget and QGraphicsGridLayout subclasses of GraphicsWidget etc. Examples:
# ci is the central item (a GraphicsLayout) of a GraphicsLayoutWidget.
# Set column spacing between first and second plot
graphicslayoutwidget
.ci.layout.setColumnSpacing(0, 100)
# Set left, top, right, bottom padding around edges of the layout
graphicslayoutwidget
.ci.layout.setContentsMargins(100, 50, 200, 10)

Patrick

JJ

unread,
May 27, 2019, 7:07:49 AM5/27/19
to pyqtgraph
Hi Patrick,
Setting the z value of the axes items worked as you suggested. However, the grid is now rendered on top of the plotted curve. Do you have an idea of how to render the curve on top?
I have tried setting the z value of the curve but this doesn't seem to help.

self.viewbox.setBackgroundColor((192,192,192))
self.myplot.getAxis("bottom").setPen({"color": (255, 255, 255), "width": 5})
self.myplot.getAxis("left").setPen({"color": (255, 255, 255), "width": 5})
for k in ['bottom', 'left']:
            axis
= self.myplot.getAxis(k)
            axis
.setZValue(1)
curve
= self.myplot.plot(self.xdata, self.ydata, pen=MYPEN)
curve
.setZValue(1e6) #this doesn't help

John

Patrick

unread,
May 28, 2019, 1:45:04 AM5/28/19
to pyqtgraph
Hi,

I can tell you why it doesn't work, but unfortunately can't immediately suggest a workaround. Here's some demo code which lists out the drawing order for all the plot items:
#!/usr/bin/env python3

from PyQt5 import QtWidgets
import pyqtgraph as pg
import numpy as np

class TestPlot(pg.GraphicsLayoutWidget):

   
def __init__(self):
       
super().__init__()
       
self.plotItem = self.addPlot()
       
self.plotItem.getViewBox().setBackgroundColor((192,192,192))
       
self.plotItem.showGrid(True)
       
self.plotItem.getAxis("bottom").setPen({"color": (255, 0, 0), "width": 5})
        plot
= self.plotItem.plot(np.random.rand(10), pen={"color": (0, 0, 0), "width": 3})

       
def format_graphicsitem_tree(gitem, newline=False):
            returnstring
= "{}: {}\n".format(gitem.zValue(), gitem)
           
for child in gitem.childItems():
                returnstring
+= "  {}\n".format(format_graphicsitem_tree(child).replace("\n", "\n  "))
           
return returnstring.rpartition("\n")[0]
       
print(format_graphicsitem_tree(self.plotItem))
 
def main():
   
import sys
    app
= QtWidgets.QApplication(sys.argv)
    mainwindow
= TestPlot()
    mainwindow
.show()
    sys
.exit(app.exec_())

if __name__ == '__main__':
    main
()

Output:
0.0: <pyqtgraph.graphicsItems.PlotItem.PlotItem.PlotItem object at 0x7fc3371b13a8>
 
-1000.0: <pyqtgraph.graphicsItems.AxisItem.AxisItem object at 0x7fc334166048>
   
0.0: <PyQt5.QtWidgets.QGraphicsTextItem object at 0x7fc3341660d8>
 
-1000.0: <pyqtgraph.graphicsItems.AxisItem.AxisItem object at 0x7fc334166168>
   
0.0: <PyQt5.QtWidgets.QGraphicsTextItem object at 0x7fc3341661f8>
 
-1000.0: <pyqtgraph.graphicsItems.AxisItem.AxisItem object at 0x7fc334166288>
   
0.0: <PyQt5.QtWidgets.QGraphicsTextItem object at 0x7fc334166318>
 
-1000.0: <pyqtgraph.graphicsItems.AxisItem.AxisItem object at 0x7fc3341663a8>
   
0.0: <PyQt5.QtWidgets.QGraphicsTextItem object at 0x7fc334166438>
 
-100.0: <pyqtgraph.graphicsItems.ViewBox.ViewBox.ViewBox object at 0x7fc3371b1708>
   
-1000000.0: <PyQt5.QtWidgets.QGraphicsRectItem object at 0x7fc3371b1828>
   
0.0: <pyqtgraph.graphicsItems.ViewBox.ViewBox.ChildGroup object at 0x7fc3371b1798>
     
0.0: <pyqtgraph.graphicsItems.PlotDataItem.PlotDataItem object at 0x7fc3341665e8>
       
0.0: <pyqtgraph.graphicsItems.PlotCurveItem.PlotCurveItem object at 0x7fc3341764c8>
       
0.0: <pyqtgraph.graphicsItems.ScatterPlotItem.ScatterPlotItem object at 0x7fc334176288>
     
1000000000.0: <PyQt5.QtWidgets.QGraphicsRectItem object at 0x7fc3371b18b8>
   
0.0: <PyQt5.QtWidgets.QGraphicsRectItem object at 0x7fc3371b1948>
 
0.0: <pyqtgraph.graphicsItems.ButtonItem.ButtonItem object at 0x7fc3371b15e8>
 
0.0: <pyqtgraph.graphicsItems.LabelItem.LabelItem object at 0x7fc3341664c8>
   
0.0: <PyQt5.QtWidgets.QGraphicsTextItem object at 0x7fc334166558>

The scene is laid out in that order. You can also see each GraphicsItem can have child items. Setting a zValue rearranges the order of sibling items (at the same indent level) only. So the background (QGraphicsRectItem with zValue -1e6) is a child of the ViewBox, as are the PlotItems. The AxisItems are siblings of the ViewBox. So changing the ZValue of an AxisItem can push the grid lines below or above all of those, but you can't fit it in between just by changing the zValue.

You may be able to do some magic by swapping graphicsItem parents around (setParent), but you may have issues with position and scaling. You could also see if you can overlay two linked ViewBoxes, one holding the background (but no axes etc) and another holding the plot and axis labels as normal.

Patrick

JJ

unread,
May 28, 2019, 3:42:25 AM5/28/19
to pyqtgraph
Hi
I found this thread, which says that setting the z order on an item is not effective if it has a parent.
Do you think this is the case here?
John
Reply all
Reply to author
Forward
0 new messages