Пример #1
0
    def paintEvent(self, event):
        w, h = self.width * self._scale, self.height * self._scale
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(QColor('black'))
        painter.setBrush(_white)
        painter.drawRect(1, 1, w, h)

        # determine positions
        beam = QPolygonF([QPointF(4, 5)])
        i = 0
        for k in [
                'nok0', 'shutter_gamma', 'nok2', 'nok3', 'nok4', 'nok5a',
                'nok5b', 'nok6', 'nok7', 'nok8'
        ]:
            v = self.values[k]
            if isinstance(v, (tuple, readonlylist)):
                x, y = v  # pylint: disable=W0633
            elif isinstance(v, int):
                x, y = 0, v
            else:
                raise Exception('%r' % type(v))
            p = self._calculatePoint(i, x, y)
            beam.append(QPointF(p[0], p[1]))
            i += 1
        x, y = self.values['nok8']
        p = self._calculatePoint(i + 1, x, y)

        painter.setPen(beambackgroundpen)
        painter.drawPolyline(beam)

        # draw beam
        painter.setPen(beampen)
        painter.drawPolyline(beam)
Пример #2
0
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(QPen(_black.color()))
        painter.setBrush(_grey)

        fontscale = float(self._scale)
        h = self.props['height'] * fontscale
        w = self.props['width'] * fontscale
        painter.drawRect(2, 10, w - 4, h / 2)

        is_in = int(self._curval[0])
        is_out = int(self._curval[1])
        lensheight = h / 2 - 25
        lensw = w / 32
        for (i, n, x) in [(0, 4, 0), (1, 6, 6), (2, 16, 14)]:
            if is_in & (1 << i):
                lensy = 22
            elif is_out & (1 << i):
                lensy = h / 2 + 20
            else:
                lensy = h / 4 + 22
            for j in range(n):
                painter.drawRect((1 + x + j) * lensw, lensy, lensw + 1,
                                 lensheight)
Пример #3
0
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        h = self._scale * 2.5 * self.props['height']
        w = self._scale * self.props['width']

        # cache pen
        pen = painter.pen()

        if self.props['name']:
            painter.setFont(self.font())
            if self._curstatus != OK:
                painter.fillRect(0, 0, w, self._scale * 2.5,
                                 statusbrush[self._curstatus])
            if self._fixed:
                painter.setPen(QPen(_blue.color()))
            else:
                painter.setPen(QPen(_black.color()))
            painter.drawText(0, 0, w, self._scale * 2.5, Qt.AlignCenter,
                             self.props['name'])
            painter.setPen(pen)
            yoff = self._scale * 2.5
        else:
            yoff = 0

        painter.setPen(QPen(_blue.color()))

        y = h * 0.5 + yoff
        painter.drawLine(0, y, w, y)
        painter.drawLine(0, y + 1, w, y + 1)
        painter.drawLine(0, y + 2, w, y + 2)

        # reset pen
        painter.setPen(pen)

        painter.setBrush(statusbrush[self._curstatus])
        if self._curstr in self.props['options']:
            self.shift = self.props['options'].index(self._curstr)
        if self._curstr in self.props['disabled_options']:
            self.shift = len(self.props['options'])

        painter.setFont(self.valueFont)

        h0 = max(2 * self._scale, 2 * self._scale + 4)
        painter.setClipRect(0, yoff, w, h)
        for i, t in enumerate(self.props['options']):
            y = h * 0.5 + yoff + h0 * (self.shift - i - 0.45)
            b = statusbrush[self._curstatus]
            if t == self._curstr:
                painter.setBrush(b)
            else:
                painter.setBrush(_grey if b == statusbrush[OK] else b)
            painter.drawRect(5, y + 2, w - 10, h0 - 4)
            painter.drawText(5, y + 2, w - 10, h0 - 4, Qt.AlignCenter, t)
Пример #4
0
    def paintEvent(self, event):
        # This method is, in practice, drawing the contents of
        # your window.

        # get current window size
        s = self.parent().size()
        qp = QPainter()
        qp.begin(self)
        qp.setRenderHint(QPainter.Antialiasing, True)
        qp.setPen(self.penColor)
        qp.setBrush(self.fillColor)
        qp.drawRect(0, 0, s.width(), s.height())
Пример #5
0
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        pen = painter.pen()

        fontscale = float(self._scale)
        painter.setFont(scaledFont(self.valueFont, 0.9))
        h = self.props['height'] * fontscale
        w = self.props['width'] * fontscale
        elwidth = w / 20.
        elheight = h / 3

        pol_bits = self.props['polarizer']
        is_in = int(self._curval[0] << pol_bits | self._curval[7])
        is_out = int(self._curval[1] << pol_bits | self._curval[8])
        x = elwidth
        y = 2.5 * fontscale
        for i in range(18):
            painter.setPen(QPen(_black.color()))
            painter.setBrush(_grey)
            painter.drawRect(x, y, elwidth - 2, elheight)
            painter.setBrush(_blue)
            if is_in & (1 << (17 - i)):
                ely = 3
            elif is_out & (1 << (17 - i)):
                ely = 2 + elheight / 2
            else:
                ely = 2 + elheight / 4
            painter.drawRect(x + 3, y + ely, elwidth - 8, elheight / 3)
            if i >= 18 - pol_bits:
                painter.setPen(QPen(_white.color()))
                painter.drawText(x + 3, y + ely - 2, elwidth - 8,
                                 elheight / 3 + 2, Qt.AlignHCenter, 'POL')
                painter.setPen(QPen(_black.color()))
            painter.drawText(x, 3, elwidth, 2 * fontscale,
                             Qt.AlignRight | Qt.AlignTop, str(19 - i))
            x += elwidth
        painter.fillRect(0, y + elheight / 3 - 5, w, 3, _yellow)
        painter.setPen(pen)

        x = elwidth + 1
        y += elheight + 4

        slhw = 1.6 * elwidth
        for i, slitpos in enumerate([20, 14, 8, 4, 2]):
            slitw, slith = self._curval[2 + i]
            xmiddle = x + ((20 - slitpos) * elwidth)
            painter.drawLine(xmiddle, y, xmiddle, y + 15)
            painter.setBrush(_white)
            painter.drawRect(xmiddle - 0.5 * slhw, y + 15, slhw, slhw)
            painter.setBrush(collstatusbrush[self._curstatus[2 + i]])
            w = (50 - slitw) * slhw / 100
            h = (50 - slith) * slhw / 100
            painter.drawRect(xmiddle - 0.5 * slhw + w, y + 15 + h,
                             slhw - 2 * w, slhw - 2 * h)
            painter.drawText(xmiddle - 0.8 * elwidth, y + 15, slhw, slhw,
                             Qt.AlignCenter, '%.1f\n%.1f' % (slitw, slith))
Пример #6
0
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setBrush(_magenta)
        painter.setRenderHint(QPainter.Antialiasing)

        w = self.props['width'] * self._scale
        h = self.props['height'] * self._scale

        if self.props['name']:
            painter.setFont(self.font())
            painter.drawText(0, 0, w, self._scale * 2.5, Qt.AlignCenter,
                             self.props['name'])
            yoff = self._scale * 2.5
        else:
            yoff = 0
        painter.setBrush(statusbrush[self._curstatus])
        painter.drawRect(2, 2 + yoff, w - 4, h - 4)
        painter.setFont(self.valueFont)
        painter.drawText(2, 2 + yoff, w - 4, h - 4, Qt.AlignCenter,
                         self._curstr)
Пример #7
0
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        fontscale = float(self._scale)
        ww = self.props['width'] * fontscale - 4
        wh = self.props['height'] * fontscale - 4
        sx, sy = self.props['maxw'], self.props['maxh']

        if self._opmode == 'offcentered':
            dx, dy, w, h = self._curval
            x0, x1, y0, y1 = dx - w / 2., dx + w / 2., dy - h / 2., dy + h / 2.
            l1, l2, l3, l4 = '(%.1f, %.1f)' % (dx, dy), '%.1f x %.1f' % (
                w, h), '', ''
        elif self._opmode == 'centered':
            w, h = self._curval
            x0, x1, y0, y1 = -w / 2., w / 2., -h / 2., h / 2.
            l1, l2, l3, l4 = '', '%.1f x %.1f' % (w, h), '', ''
        elif self._opmode.startswith('4blades'):
            x0, x1, y0, y1 = self._curval
            l1, l2, l3, l4 = '%.1f' % y1, '%.1f' % y0, '%.1f' % x0, '%.1f' % x1
            if self._opmode.endswith('opposite'):
                x0 *= -1
                y0 *= -1

        x0 = (x0 + sx / 2) / sx * ww
        x1 = (x1 + sx / 2) / sx * ww
        y0 = wh - (y0 + sy / 2) / sy * wh
        y1 = wh - (y1 + sy / 2) / sy * wh

        painter.setPen(QPen(_black.color()))
        painter.setBrush(_white)
        painter.drawRect(2, 2, ww, wh)
        painter.setBrush(collstatusbrush[self._curstatus])
        painter.drawRect(2 + x0, 2 + y1, x1 - x0, y0 - y1)

        painter.setFont(scaledFont(self.valueFont, 0.8))
        painter.drawText(2, 2, ww, wh, Qt.AlignTop | Qt.AlignHCenter, l1)
        painter.drawText(2, 2, ww, wh, Qt.AlignBottom | Qt.AlignHCenter, l2)
        painter.drawText(2, 2, ww, wh, Qt.AlignVCenter | Qt.AlignLeft, l3)
        painter.drawText(2, 2, ww, wh, Qt.AlignVCenter | Qt.AlignRight, l4)
Пример #8
0
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setBrush(QBrush(self.color))
        painter.setRenderHint(QPainter.Antialiasing)

        fontscale = float(self._scale)
        h = self.props['height'] * fontscale
        w = self.props['width'] * fontscale
        posscale = (w - 100) / self.props['posscale']

        # Draw name above tube
        if self.props['name']:
            painter.setFont(self.font())
            painter.drawText(5, 0, w, fontscale * 2.5, Qt.AlignCenter,
                             self.props['name'])
            yoff = fontscale * 2.5
        elif self.props['smalldet']:
            yoff = 50
        else:
            yoff = 0

        # Draw tube
        painter.setPen(self.color)
        painter.drawEllipse(5, 5 + yoff, 50, h)
        painter.drawRect(30, 5 + yoff, w - 50, h)
        painter.setPen(QColor('black'))
        painter.drawArc(5, 5 + yoff, 50, h, 1440, 2880)
        painter.drawLine(30, 5 + yoff, w - 25, 5 + yoff)
        painter.drawLine(30, 5 + yoff + h, w - 25, 5 + yoff + h)
        painter.drawEllipse(w - 45, 5 + yoff, 50, h)

        if self.props['smalldet']:
            sw = 20
            sx = 30 + self.props['smalldet'] * posscale
            painter.setPen(self.color)
            painter.drawRect(sx - sw, 2, 2 * sw, yoff + 10)
            painter.setPen(QColor('black'))
            painter.drawLine(sx - sw, 5 + yoff, sx - sw, 2)
            painter.drawLine(sx - sw, 2, sx + sw, 2)
            painter.drawLine(sx + sw, 2, sx + sw, 5 + yoff)

        # draw detector
        pos_val = self._curval[0]
        if pos_val is not None:
            pos_status = self._curstatus[0]
            pos_str = self._curstr[0]
            x_val = self._curval[1]
            x_status = self._curstatus[1]
            x_str = '%.1f x' % x_val
            y_val = self._curval[2]
            y_status = self._curstatus[2]
            y_str = '%.1f y' % y_val

            stat = max(pos_status, x_status, y_status)
            painter.setBrush(statusbrush[stat])
            painter.setFont(self.valueFont)
            painter.resetTransform()
            # Translate to detector position
            xp = 30 + pos_val * posscale
            painter.translate(xp + fontscale / 2., 15 + yoff + (h - 20) / 2.)
            painter.drawRect(-fontscale / 2., -(h - 20) / 2., fontscale,
                             h - 20)
            painter.resetTransform()
            # Put X/Y values left or right of detector depending on position
            if pos_val < 14:
                xoff = 2 * fontscale
            else:
                xoff = -8.5 * fontscale
            # X translation
            painter.drawText(xp + xoff, yoff + 2 * fontscale, 7 * fontscale,
                             2 * fontscale, Qt.AlignRight, x_str)
            # Y translation
            painter.drawText(xp + xoff, yoff + 3.5 * fontscale, 7 * fontscale,
                             2 * fontscale, Qt.AlignRight, y_str)
            # Z position
            minx = max(0, xp + 5 - 4 * fontscale)
            painter.drawText(minx, h + 10 + yoff, 8 * fontscale, 30,
                             Qt.AlignCenter, pos_str)

            # draw beamstop
            if self.props['beamstop']:
                painter.setPen(QPen(_blue.color()))
                painter.drawRect(xp - 8,
                                 yoff + 15 + posscale / 350 * (1100 - y_val),
                                 2, 10)

        # draw small detector
        if self.props['smalldet'] and self._curval[4] is not None:
            x_status = self._curstatus[3]
            x_str = '%4.1f x' % self._curval[3]
            y_status = self._curstatus[4]
            y_val = self._curval[4]
            y_str = '%4.0f y' % y_val
            stat = max(x_status, y_status)

            painter.setBrush(statusbrush[stat])
            painter.setPen(QPen(_black.color()))
            painter.setFont(self.valueFont)
            sy = 10 + y_val * posscale / 250
            painter.drawRect(sx - fontscale / 2., sy, fontscale, 30)

            painter.drawText(sx - 10.5 * fontscale, sy, 8 * fontscale,
                             2 * fontscale, Qt.AlignRight, x_str)
            painter.drawText(sx - 10.5 * fontscale, sy + 1.5 * fontscale,
                             8 * fontscale, 2 * fontscale, Qt.AlignRight,
                             y_str)
Пример #9
0
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setBrush(QBrush(self.color))
        painter.setRenderHint(QPainter.Antialiasing)

        fontscale = float(self._scale)
        h = self.props['height'] * fontscale
        w = self.props['width'] * fontscale
        posscale = (w - 120) / self.props['posscale']

        if self.props['name']:
            painter.setFont(self.font())
            painter.drawText(5, 0, w, fontscale * 2.5, Qt.AlignCenter,
                             self.props['name'])
            yoff = fontscale * 2.5
        else:
            yoff = 0

        painter.setPen(self.color)
        painter.drawEllipse(5, 5 + yoff, 50, h)
        painter.drawRect(30, 5 + yoff, w - 50, h)
        painter.setPen(QColor('black'))
        painter.drawArc(5, 5 + yoff, 50, h, 1440, 2880)
        painter.drawLine(30, 5 + yoff, w - 25, 5 + yoff)
        painter.drawLine(30, 5 + yoff + h, w - 25, 5 + yoff + h)
        painter.drawEllipse(w - 45, 5 + yoff, 50, h)

        # draw Detector 1
        minx = 0
        pos_val = self._curval[0]
        if pos_val is not None:
            pos_status = self._curstatus[0]
            pos_str = self._curstr[0]
            shift_val = self._curval[1]
            shift_status = self._curstatus[1]
            shift_str = self._curstr[1]
            if shift_val > 0:
                shift_str += ' ↓'
            elif shift_val < 0:
                shift_str += ' ↑'
            # Not used at the moment, prepared for later use
            tilt_val = self._curval[2]
            tilt_status = self._curstatus[2]
            tilt_str = self._curstr[2]
            if tilt_str.endswith('deg'):
                tilt_str = tilt_str[:-3] + '°'

            stat = max(pos_status, shift_status, tilt_status)
            painter.setBrush(statusbrush[stat])
            # tf = QTransform()
            # tf.rotate(tilt_val)
            painter.resetTransform()
            painter.translate(60 + pos_val * posscale + fontscale / 2.,
                              15 + yoff + shift_val * posscale + (h - 20) / 2.)
            painter.rotate(-tilt_val)
            painter.drawRect(-fontscale / 2., -(h - 20) / 2., fontscale,
                             h - 20)  # XXX tilt ???
            painter.resetTransform()
            painter.setFont(self.valueFont)
            painter.drawText(
                60 + pos_val * posscale - 10.5 * fontscale,
                -5 + yoff + h - fontscale,  # + (shift_val - 4) * posscale,
                9.5 * fontscale,
                2 * fontscale,
                Qt.AlignRight,
                tilt_str)
            painter.drawText(
                60 + pos_val * posscale - 6.5 * fontscale,
                yoff + fontscale,  # + (shift_val - 4) * posscale,
                9.5 * fontscale,
                2 * fontscale,
                Qt.AlignLeft,
                shift_str)
            minx = max(minx, 60 + pos_val * posscale + 5 - 4 * fontscale)
            painter.drawText(minx, h + 10 + yoff, 8 * fontscale, 30,
                             Qt.AlignCenter, pos_str)
            minx = minx + 8 * fontscale
Пример #10
0
    def paintEvent(self, event):
        s = self.size()
        w, h = s.width(), s.height()
        # calculate the maximum length if all elements in a line
        maxL = self.values['Lms'] + self.values['Lsa'] + self.values['Lad']
        # add the size of the Monochromator and detector
        scale = min((w / 2 - anaradius) / float(maxL),
                    (h - monoradius - anaradius) / float(maxL))

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        painter.setPen(QColor('black'))
        painter.setBrush(_white)
        painter.drawRect(0, 0, w, h)

        # determine positions

        # incoming beam
        if self.values['mth'] < 0:
            bx, by = 3, h - (2 + monoradius)
        else:
            bx, by = 3, 2 + monoradius
        # monochromator
        mx, my = w / 2., by

        # sample
        L = self.values['Lms'] * scale  # length is in mm -- scale down a bit
        mttangle = self.values['mtt'] * deg2rad
        mttangle_t = self.targets['mtt'] * deg2rad
        if self.values['mth'] < 0:
            mttangle = -mttangle
            mttangle_t = -mttangle_t

        sx, sy = mx + L * cos(mttangle), my - L * sin(mttangle)
        sx_t, sy_t = mx + L * cos(mttangle_t), my - L * sin(mttangle_t)

        # analyzer
        L = self.values['Lsa'] * scale  # length is in mm -- scale down a bit
        sttangle = self.values['stt'] * deg2rad
        sttangle_t = self.targets['stt'] * deg2rad
        if self.values['sth'] < 0:
            sttangle = mttangle - sttangle
            sttangle_t = mttangle_t - sttangle_t
        else:
            sttangle = mttangle + sttangle
            sttangle_t = mttangle_t + sttangle_t
        ax, ay = sx + L * cos(sttangle), sy - L * sin(sttangle)
        ax_t, ay_t = sx_t + L * cos(sttangle_t), sy_t - L * sin(sttangle_t)

        # detector
        L = self.values['Lad'] * scale  # length is in mm -- scale down a bit
        attangle = self.values['att'] * deg2rad
        attangle_t = self.targets['att'] * deg2rad
        if self.values['ath'] < 0:
            attangle = sttangle - attangle
            attangle_t = sttangle_t - attangle_t
        else:
            attangle = sttangle + attangle
            attangle_t = sttangle_t + attangle_t

        dx, dy = ax + L * cos(attangle), ay - L * sin(attangle)
        dx_t, dy_t = ax_t + L * cos(attangle_t), ay_t - L * sin(attangle_t)

        # draw table "halos"
        painter.setPen(nopen)
        if self.status['mth'] != OK:
            painter.setBrush(statusbrush[self.status['mth']])
            painter.drawEllipse(QPoint(mx, my), monoradius + halowidth,
                                monoradius + halowidth)
        elif self.status['mtt'] != OK:
            painter.setBrush(statusbrush[self.status['mtt']])
            painter.drawEllipse(QPoint(mx, my), monoradius + halowidth,
                                monoradius + halowidth)
        if self.status['sth'] != OK:
            painter.setBrush(statusbrush[self.status['sth']])
            painter.drawEllipse(QPoint(sx, sy), sampleradius + halowidth,
                                sampleradius + halowidth)
        elif self.status['stt'] != OK:
            painter.setBrush(statusbrush[self.status['stt']])
            painter.drawEllipse(QPoint(sx, sy), sampleradius + halowidth,
                                sampleradius + halowidth)
        if self.status['ath'] != OK:
            painter.setBrush(statusbrush[self.status['ath']])
            painter.drawEllipse(QPoint(ax, ay), anaradius + halowidth,
                                anaradius + halowidth)
        elif self.status['att'] != OK:
            painter.setBrush(statusbrush[self.status['att']])
            painter.drawEllipse(QPoint(ax, ay), anaradius + halowidth,
                                anaradius + halowidth)

        # draw table targets
        painter.setPen(targetpen)
        painter.setBrush(_nobrush)
        painter.drawEllipse(QPoint(sx_t, sy_t), sampleradius - .5,
                            sampleradius - .5)
        painter.drawEllipse(QPoint(ax_t, ay_t), anaradius - .5, anaradius - .5)
        painter.drawEllipse(QPoint(dx_t, dy_t), detradius - .5, detradius - .5)

        # draw the tables
        painter.setPen(defaultpen)
        painter.setBrush(monotablebrush)
        painter.drawEllipse(QPoint(mx, my), monoradius, monoradius)
        painter.setBrush(sampletablebrush)
        painter.drawEllipse(QPoint(sx, sy), sampleradius, sampleradius)
        painter.setBrush(anatablebrush)
        painter.drawEllipse(QPoint(ax, ay), anaradius, anaradius)
        painter.setBrush(dettablebrush)
        painter.drawEllipse(QPoint(dx, dy), detradius, detradius)
        painter.setBrush(_white)
        painter.setPen(nopen)
        painter.drawEllipse(QPoint(mx, my), monoradius / 2, monoradius / 2)
        # painter.drawEllipse(QPoint(sx, sy), 20, 20)
        painter.drawEllipse(QPoint(ax, ay), anaradius / 2, anaradius / 2)
        # painter.drawEllipse(QPoint(dx, dy), 20, 20)

        beam = QPolygonF([
            QPointF(bx, by),
            QPointF(mx, my),
            QPointF(sx, sy),
            QPointF(ax, ay),
            QPointF(dx, dy)
        ])
        painter.setPen(beambackgroundpen)
        painter.drawPolyline(beam)

        # draw mono crystals
        painter.setPen(monopen)
        mthangle = -self.values['mth'] * deg2rad
        painter.drawLine(mx + 10 * cos(mthangle), my - 10 * sin(mthangle),
                         mx - 10 * cos(mthangle), my + 10 * sin(mthangle))

        # draw ana crystals
        athangle = -self.values['ath'] * deg2rad
        alpha = athangle + sttangle
        # TODO if the angle is too small then it could be that the ath value
        # must be turned by 90 deg (PANDA: chair setup) ??
        if attangle < 0 and alpha < attangle:
            alpha += pi_2
        painter.drawLine(ax + 10 * cos(alpha), ay - 10 * sin(alpha),
                         ax - 10 * cos(alpha), ay + 10 * sin(alpha))

        # draw sample
        painter.setPen(samplepen)
        painter.setBrush(samplebrush)
        sthangle = self.values['sth'] * deg2rad
        alpha = sthangle + mttangle + pi_4
        # painter.drawRect(sx - 5, sy - 5, 10, 10)
        sz = 10
        painter.drawPolygon(
            QPolygonF([
                QPointF(sx + sz * cos(alpha), sy - sz * sin(alpha)),
                QPointF(sx + sz * cos(alpha + pi_2),
                        sy - sz * sin(alpha + pi_2)),
                QPointF(sx - sz * cos(alpha), sy + sz * sin(alpha)),
                QPointF(sx - sz * cos(alpha + pi_2),
                        sy + sz * sin(alpha + pi_2)),
                QPointF(sx + sz * cos(alpha), sy - sz * sin(alpha))
            ]))

        painter.setPen(samplecoordpen)
        sr = sampleradius
        for angle in [alpha - pi_4, alpha - 3 * pi_4]:
            painter.drawLine(sx - sr * cos(angle), sy + sr * sin(angle),
                             sx + sr * cos(angle), sy - sr * sin(angle))

        # draw detector
        painter.setPen(monopen)
        painter.setBrush(_white)
        painter.drawEllipse(QPoint(dx, dy), 4, 4)

        # draw beam
        painter.setPen(beampen)
        painter.drawPolyline(beam)