Пример #1
0
class RulerWindow(QWidget):
    def __init__(self, *args, **kwargs):
        super(RulerWindow, self).__init__(*args, **kwargs)
        self.setWindowTitle("Screen Ruler")
        self.setWindowIcon(QIcon("ruler.ico"))
        self.initial_dots = []
        self.final_dots = []

        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
                            | Qt.WindowSystemMenuHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.ignored = False
        self.setMouseTracking(True)
        self.custom_cursor = self.generate_custom_cursor()
        #self.setCursor(Qt.BlankCursor)
        self.setCursor(self.custom_cursor)

    def set_sizes(self, h_res, v_res, size):
        if h_res == "auto":
            screen = self.screen()
            self.ppix = screen.physicalDotsPerInchX()
            self.ppiy = screen.physicalDotsPerInchY()
            h_res = screen.geometry().width()
            v_res = screen.geometry().height()
            #if self.ppix != self.ppiy:
            #    print("WARNING! due to the properties of your screen angles are slightly distorted and length of diagonals are approximations")
        else:
            diagonal_res = math.sqrt(int(h_res)**2 + int(v_res)**2)
            self.ppix = diagonal_res / float(size)  # Pixels per inch
            self.ppiy = self.ppix

        self.preview = Preview(h_res, v_res, self)
        self.preview.show()
        self.h_res, self.v_res = h_res, v_res

    def paintEvent(self, event):
        painter = QPainter()
        painter.begin(self)
        if not self.ignored:
            self.paint_background(painter)
        painter.setPen(QColor(255, 0, 255))
        painter.setBrush(QColor(0, 0, 0))

        for index, i in enumerate(self.initial_dots):
            painter.setPen(QColor(255, 0, 255))
            painter.drawRect(i.x() - 1, i.y() - 1, 2, 2)
            try:
                end_point = self.final_dots[index]
                painter.setPen(QColor(0, 0, 255))
                moving = False
            except IndexError:
                # There is no end point, so cursor is end point
                end_point = self.cursor().pos()
                painter.setPen(QColor(0, 0, 255, 64))
                moving = True

            mid_point = QPoint(end_point.x(), i.y())
            painter.drawPolyline(i, mid_point, end_point, i)
            painter.setPen(QColor(255, 0, 255))
            halfx = (mid_point.x() - i.x()) / 2 + i.x()
            halfy = (end_point.y() - mid_point.y()) / 2 + mid_point.y()

            # Draw perpendicular magenta lines in each of the triangle's sides' center
            top_horizontal_half = QPoint(halfx, i.y() + 10)
            bot_horizontal_half = QPoint(halfx, i.y() - 10)

            left_vertical_half = QPoint(end_point.x() - 10, halfy)
            right_vertical_half = QPoint(end_point.x() + 10, halfy)
            try:
                hipotenuse = math.sqrt((2 * (halfx - i.x()))**2 +
                                       (2 * (halfy - mid_point.y()))**2)
                scaling_factor = hipotenuse / 10  # To ensure line length = 10
                y_change = (2 * (halfx - i.x()) / scaling_factor)
                x_change = (2 * (halfy - mid_point.y()) / scaling_factor)

            except ZeroDivisionError:
                y_change = 0
                x_change = 0

            top_hipotenuse_half = QPoint(halfx - x_change, halfy + y_change)
            bot_hipotenuse_half = QPoint(halfx + x_change, halfy - y_change)

            if hipotenuse >= 20 and moving:  # To not be in the way while looking for a second point
                painter.drawLine(top_horizontal_half, bot_horizontal_half)
                painter.drawLine(left_vertical_half, right_vertical_half)
                painter.drawLine(top_hipotenuse_half, bot_hipotenuse_half)

            painter.setPen(QColor(255, 255, 255))
            x_px = abs(int((halfx - i.x()) * 2)) + 1
            y_px = abs(int((halfy - mid_point.y()) * 2)) + 1
            hipotenuse = abs(hipotenuse)
            inch_to_cm = 2.54
            x_inches = x_px / self.ppix
            y_inches = y_px / self.ppiy
            hip_inches = hipotenuse / ((self.ppiy + self.ppix) / 2)
            x_cm = x_inches * inch_to_cm
            y_cm = y_inches * inch_to_cm
            hip_cm = hip_inches * inch_to_cm
            x_text = str(
                x_px
            ) + "px | " + f"{x_cm:7.2f}" + "cm | " + f"{x_inches:7.2f}" + "inch"
            y_text = str(
                y_px
            ) + "px | " + f"{y_cm:7.2f}" + "cm | " + f"{y_inches:7.2f}" + "inch"
            hip_text = f"{abs(hipotenuse):7.2f}" + "px | " + f"{hip_cm:7.2f}" + "cm | " + f"{hip_inches:7.2f}" + "inch"
            # in 7.2f -> 7 = max char, 2 = max floating point precision
            if moving and hipotenuse >= 20:  # To not be in the way while looking for a second point
                painter.drawText(QPoint(halfx, i.y()), x_text)
                painter.drawText(QPoint(end_point.x(), halfy), y_text)
                painter.drawText(
                    QPoint(halfx, halfy - 12),
                    hip_text)  # 7 = max char, 2 = max floating point precision
            elif not moving:
                # drawStaticText is more optimized if it rarely updates
                painter.drawStaticText(QPoint(halfx, i.y()),
                                       QStaticText(x_text))
                painter.drawStaticText(QPoint(end_point.x(), halfy),
                                       QStaticText(y_text))
                painter.drawStaticText(QPoint(halfx, halfy - 12),
                                       QStaticText(hip_text))

        painter.setPen(QColor(255, 0, 255))
        for i in self.final_dots:
            painter.drawRect(i.x() - 1, i.y() - 1, 2, 2)
        """if not self.ignored:
            self.paint_cursor(painter)"""
        painter.end()

    def paint_background(self, painter):
        painter.setBrush(QColor(0, 0, 0, 120))  # Semitransparent brush
        painter.setPen(Qt.NoPen)
        corners = self.preview.screen_corners

        # drawRect(left margin, top margin, width, height)
        # corners[0] = top left corner
        # corners[1] = bot right corner
        # corners[][0] = x component
        # corners[][1] = y component

        # black rectangle
        # topleft corner =  (screen left, screen top)
        # botright corner = (preview left, screen bottom)
        painter.drawRect(0, 0, corners[0][0], self.v_res)
        # black rectangle
        # topleft corner =  (preview left, screen top)
        # botright corner = (preview right, preview top)
        painter.drawRect(corners[0][0], 0, corners[1][0] - corners[0][0],
                         corners[0][1])
        # black rectangle
        # topleft corner =  (preview left, preview bottom)
        # botright corner = (preview right, screen bottom)
        painter.drawRect(corners[0][0], corners[1][1],
                         corners[1][0] - corners[0][0],
                         self.v_res - corners[1][1])
        # black rectangle
        # topleft corner =  (preview right, screen top)
        # botright corner = (preview right, screen bot)
        painter.drawRect(corners[1][0], 0, self.h_res - corners[1][0],
                         self.v_res)
        painter.setPen(QColor(
            255, 255, 255,
            1))  # Almost transparent brush, just so there is something there
        painter.setBrush(QColor(
            0, 0, 0,
            1))  # Almost transparent brush, just so there is something there
        # transparent rectangle with blue border
        # topleft corner =  (preview left, preview top)
        # botright corner = (preview right, preview bottom)
        painter.drawRect(corners[0][0] - 1, corners[0][1] - 1,
                         corners[1][0] - corners[0][0] + 1,
                         corners[1][1] - corners[0][1] + 1)
        """painter.setBrush(QColor(255, 255, 255, 255))
        painter.drawRect(corners[0][0]+10, # 1 white dot where the cursor is
                         corners[0][1]+10,
                         1,
                         1
        )"""

    def mousePressEvent(self, event):
        if len(self.initial_dots) == len(self.final_dots):
            self.initial_dots.append(event.pos())
        else:
            self.final_dots.append(event.pos())
        self.repaint()
        self.preview.update()

    def mouseDoubleClickEvent(self, event):
        self.final_dots = []
        self.initial_dots = []
        self.update()
        self.preview.update()

    def mouseMoveEvent(self, event):
        self.preview.update_pos()
        self.repaint()
        self.preview.update()

    def keyPressEvent(self, event):
        key = event.key()
        if key in [16777234, 16777235, 16777236, 16777237]:  # Arrows
            cursor = self.cursor()
            x = cursor.pos().x()
            y = cursor.pos().y()
            if key == 16777234:  # Left arrow
                new_x, new_y = (x - 1, y)
            if key == 16777235:  # Up arrow
                new_x, new_y = (x, y - 1)
            if key == 16777236:  # Right arrow
                new_x, new_y = (x + 1, y)
            if key == 16777237:  # Down arrow
                new_x, new_y = (x, y + 1)
            cursor.setPos(new_x, new_y)
        elif key == 80:  # P key
            self.ignore_input(not self.ignored)
        elif key == 16777220:  # Enter key
            # Simulate click
            self.mousePressEvent(self.cursor())
        self.preview.repaint()

    def ignore_input(self, ignore=True):
        self.ignored = ignore
        self.setMouseTracking(not ignore)
        flags = Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.WindowSystemMenuHint
        if ignore:
            flags = flags | Qt.WindowTransparentForInput
        self.setWindowFlags(flags)
        self.showFullScreen()
        if ignore:
            cursor = Qt.ArrowCursor
            self.preview.hide()
        else:
            self.preview.show()
            cursor = Qt.BlankCursor
        self.setCursor(cursor)

    def generate_custom_cursor(self):
        print(QPixmap.defaultDepth())
        bitmap = QPixmap(QSize(32, 32))
        mask = QPixmap(QSize(32, 32))
        bitmap.fill(QColor("#ffffff"))
        mask.fill(QColor("#ffffff"))

        x, y = Preview.M_SIZE
        painter = QPainter(bitmap)
        painter.setPen(QColor("#000000"))
        painter.drawRect(0, 0, x + 2, y + 2)
        painter.drawLine(x / 2 + 2, 1, x / 2 + 2, y + 1)
        painter.drawLine(1, y / 2 + 2, x + 1, y / 2 + 2)
        painter.end()

        return QCursor(QBitmap(bitmap), QBitmap(mask), (x + 2) / 2,
                       (y + 2) / 2)