Search code examples
pythonqtpyqtqgraphicsviewbrush

Setting pattern colours and line thickness on QtCore.Qt.CrossPattern


I'm using the following in the init of my QtGui.QGraphicsView to make a nice grid/cross pattern. But not sure how to change the background color or thickness of the cross pattern lines? Using setColor to set the color, but this only changes the color of the crossPattern and not the background.

Is there a way to change these, or should I be using a different type of style?

import PySide.QtGui as QtGui
import PySide.QtCore as QtCore

class NodeGraphView(QtGui.QGraphicsView):

    def __init__(self, parent):
        super(NodeGraphView, self).__init__(parent)

        self.fg_brush = QtGui.QBrush()
        self.fg_brush.setStyle(QtCore.Qt.CrossPattern)
        self.fg_brush.setColor(QtGui.QColor(42, 42, 42, 255))

        self.setBackgroundBrush(self.fg_brush)

Solution

  • The view background is basically just for the "fill"; the cross pattern is very basic and not configurable (other than color, because that's basic fill property). But it is not difficult to draw your own grid, and then you have much more control (such as thickness, dotted/dashed, showing origin, etc):

    • create pen for grid lines: give it color and width
    • You can set the pen to have a constant "cosmetic" width; in that case, it won't scale
    • add lines to scene
    • set lines to have lowest z value so they are drawn before everything else

    Example:

    from PyQt5.QtCore import QTimer, Qt
    from PyQt5.QtGui import QPen
    from PyQt5.QtWidgets import QApplication, QGraphicsScene, QGraphicsView
    
    scale_fac = 1
    
    def scale():
        global scale_fac
        scale_fac = scale_fac * 1.5
        view.scale(scale_fac, scale_fac)
    
    app = QApplication([])
    
    scene = QGraphicsScene()
    pen = QPen(Qt.red)
    pen.setCosmetic(True)  # ***
    for x in range(0, 500, 50):
        line = scene.addLine( x, 0, x, 500, pen)
        line.setZValue(-10)
    for y in range(0, 500, 50):
        scene.addLine( 0, y, 500, y, pen)
        line.setZValue(-10)
    
    view = QGraphicsView()
    view.setScene(scene)
    view.show()
    
    QTimer.singleShot(1000, scale)
    QTimer.singleShot(2000, scale)
    QTimer.singleShot(3000, scale)
    app.exec()
    

    If setCosmetic(True) is not issued, the line thickness will increase as you zoom in.

    The nice thing with the above is that the lines are at a fixed coordinate in the scene. However, if you zoom out, you may have to add more lines, or make the existing lines longer. You could do this by overriding the scene's drawBackground(), which gets called with the rect of the scene that is in view: there you adjust the line endpoints.