Color picker update

 
colorDialog
Here’s an update of the color picker I did last year.

The color picker has now been updated to use PyQt5 and PySide2 for use in Python 3. That’s the biggest update to it (I think). I’ve also increased the area where the mouse can adjust the value – that arc along the left of the color wheel – so it’s easier to grab.
 
zoom

The pick button has also been reworked. As before, the pick button will take a screenshot of your desktop and display it, then clicking anywhere on that will select the color the mouse was at. For one, taking a screenshot works differently in PyQt5/PySide2 so that part had to be rewritten. But the other part is that pixels are so tiny! So as seen above, there is now a magnifier with the pick button!

When the pick button displays the screenshot, it uses a QGraphicsView and QGraphicsScene. The scene holds both the screenshot and the magnifier. The magnifier is a subclass of a QGraphicsPixmapItem, which also holds the screenshot. This subclass constantly moves with the mouse, takes its position, grabs a small section of the screenshot at that position and displays it at a much larger size.  It looks like this:

class magnifier(QGraphicsPixmapItem):
    "zoomed in view around mouse\nfrom Orthallelous"
    # could use QGraphicsPixmapItem's built-in scale function
    # but then wouldn't be able to have the fancy grid
    # and that's what matters!

    def __init__(self, parent=None):
        super(magnifier, self).__init__(parent)

        self.setFlags(QGraphicsItem.ItemIsMovable)
        self.setAcceptHoverEvents(True)#setAcceptsHoverEvents(True)
        
        self.zoom = self.width = self.height = 10
        self.size = QSize(self.width, self.height)

        # +zw, zh so the mouse isn't sitting on the grid itself
        zw = 0 if self.width % 2 else self.zoom
        zh = 0 if self.height % 2 else self.zoom
        self.offset = QPoint((self.width  * self.zoom + zw) // 2,
                             (self.height * self.zoom + zh) // 2)
        
        self.background = None
        self.setPos(QCursor().pos() - self.offset)


    def drawGrid(self, image):
        "draws a grid on image"
        img = QPixmap(image.width() + 1, image.height() + 1)
        p = QPainter(img); p.drawPixmap(1, 1, image)
        # the +1 is for the grid around the image; otherwise grid is cut off
        
        w, h, z = img.width(), img.height(), self.zoom
        for i in range(max(self.width, self.height) + 1):
            p.drawLine(QPoint(0, i * z), QPoint(w, i * z)) # horiztonal lines
            p.drawLine(QPoint(i * z, 0), QPoint(i * z, h)) # vertical lines
                       
        return img

    def setBackground(self, img):
        self.background = img; self._readjust()

    def setSize(self, w, h):
        self.width = w; self.height = h; self._readjust()

    def setZoom(self, z):
        self.zoom = z; self._readjust()

    def _readjust(self):
        "re-set some things"
        w, h, z = self.width, self.height, self.zoom
        zw = 0 if w % 2 else z; zh = 0 if h % 2 else z
        
        self.size = QSize(w, h)
        self.offset = QPoint((w * z + zw) // 2, (h * z + zh) // 2)

        pos = QCursor().pos() - self.offset
        self.setPos(pos); self._setView(pos)
    
    def _setView(self, pos):
        "grab viewpoint around pos, set as image"
        if self.background is None: return

        topLeft = pos - QPoint(self.width // 2, self.height // 2)
        try: topLeft = topLeft.toPoint()
        except: pass  # ugh
        
        rect = QRect(topLeft, self.size)
        img = self.background.copy(rect)  # crop small section
        
        w, h, z = img.width(), img.height(), self.zoom  # scale small section
        img = img.scaled(w * z, h * z, Qt.KeepAspectRatio)
        self.setPixmap(self.drawGrid(img))

    def hoverMoveEvent(self, event):
        pos = event.scenePos()
        self.setPos(pos - self.offset)
        self._setView(pos)

Note that this graphics item tracks the mouse and moves itself, not by the graphics scene. So if you move the mouse too fast, it may get outside of the item’s tracking ability and so the magnifier may stop moving. Just put the mouse back on it for it to start following again.

As for the rest of the color picker code, you may view it here. I’ve also placed an MIT license on the color picker, so enjoy. If you’re wondering about just the magnifier code above, uh… public domain!

Then after I updated this, I made this thing which may or may not appear in the next month’s post!
charmony

Tagged with: ,
Posted in Python

Leave a comment

In Archive
Design a site like this with WordPress.com
Get started