Skip to content

create internals.PrimitiveArray#2591

Merged
j9ac9k merged 1 commit intopyqtgraph:masterfrom
pijyoi:refactor-drawarray
Jan 26, 2023
Merged

create internals.PrimitiveArray#2591
j9ac9k merged 1 commit intopyqtgraph:masterfrom
pijyoi:refactor-drawarray

Conversation

@pijyoi
Copy link
Copy Markdown
Contributor

@pijyoi pijyoi commented Jan 24, 2023

Refactor the array code in ScatterPlotItem and PlotCurveItem into PrimitiveArray.

It may look as though that there is one behavior change made in this PR. Previously in ScatterPlotItem, if the number of items was zero, then the call to drawPixmapFragments would be skipped.
I have looked through the logs, and this skipping behavior was added when adding support for PyQt's sip.array. Testing shows that PyQt does currently support zero-length sip arrays. I suspect it was added when testing against preliminary versions of sip.array.

Script to verify that zero-length sip.array(s) work.

from PyQt6 import QtCore, QtGui, sip

app = QtGui.QGuiApplication([])
array = sip.array(QtGui.QPainter.PixmapFragment, 0)
print(array)

pix = QtGui.QPixmap(51, 51)
pix.fill(QtCore.Qt.GlobalColor.cyan)

qimg = QtGui.QImage(200, 200, QtGui.QImage.Format.Format_RGB32)
qimg.fill(QtCore.Qt.GlobalColor.white)
painter = QtGui.QPainter(qimg)
painter.drawPixmapFragments(array, pix)
painter.end()

print('done')

Besides cleaning up the code, this PR will hopefully make it simpler to add support for drawRects and drawPoints.

Sample script to exercise drawRects using this PR. This may help #2287.

import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui, QtWidgets

class CheckerBoardItem(pg.GraphicsObject):
    def __init__(self, size):
        super().__init__()
        self.size = size

        x = np.arange(self.size)
        y = np.arange(self.size)[:, np.newaxis]
        bitmap = (y & 1) ^ (x & 1)
        X, Y = np.meshgrid(x, y)
        nzidx = bitmap.nonzero()

        self.array = pg.Qt.internals.PrimitiveArray(QtCore.QRectF, 4)
        self.array.resize(nzidx[0].size)
        memory = self.array.ndarray()
        memory[:, 0] = X[nzidx]
        memory[:, 1] = Y[nzidx]
        memory[:, 2:4] = 1

    def paint(self, painter, *args):
        rect = QtCore.QRectF(0, 0, self.size, self.size)
        painter.fillRect(rect, QtCore.Qt.GlobalColor.blue)

        inst = self.array.instances()
        painter.setPen(QtCore.Qt.PenStyle.NoPen)
        painter.setBrush(QtCore.Qt.GlobalColor.white)
        painter.drawRects(inst)

    def boundingRect(self):
        return QtCore.QRectF(0, 0, self.size, self.size)

pg.mkQApp()
pw = pg.PlotWidget()
pw.show()
cbi = CheckerBoardItem(32)
pw.addItem(cbi)
pg.exec()

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jan 24, 2023

Hi @pijyoi I love this PR. Migrating this complexity from the GraphicsItems themselves to Qt.internals was absolutely the right thing to do. Abstracting PrimativeArray to work with all bindings, regardless of whether they support the lower-level methods is fantastic.

My one nit-pick is that we should probably stay away from descriptions like "newer" and "older" regarding the versions of Qt bindings and just specify which version sip.array was introduced explicitly (or I suppose, more specifically PyQt[56]-sip. Hopefully that PR in pyside will be merged soon and we'll get equivalent performance improvements from those bindings as well.

@pijyoi
Copy link
Copy Markdown
Contributor Author

pijyoi commented Jan 24, 2023

I used more general language in the comments and let the code document itself as to the exact versions required.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Jan 26, 2023

I used more general language in the comments and let the code document itself as to the exact versions required.

Saw that, but before you know it, 10 years will have passed :D

If you'd rather leave it as is, that's fine with me. This class has fantastic comments as it is. Merging

@j9ac9k j9ac9k merged commit 48453e7 into pyqtgraph:master Jan 26, 2023
@pijyoi pijyoi deleted the refactor-drawarray branch January 26, 2023 08:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants