лучший способ обновить растровое изображение qlabel с помощью qpushbutton в Pyside2 - PullRequest
0 голосов
/ 01 августа 2020

Я собираю для своих учеников простую математическую головоломку под названием Diffy.

Я могу заставить ее работать, но способ обновления qlabel (pixmap) очень хакерский.

Я в основном пересматриваю -инициализировал все qobject-ы при нажатии qpushbutton. Вы можете увидеть это в функции button_click.

Я пытался вызвать update () для qlabel, layout, qwidget, но ни один из них не работал.

Пожалуйста, дайте мне знать, есть ли более элегантный способ .

import sys
from collections import namedtuple

from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import Qt, QPoint


class Canvas(QtWidgets.QLabel):
    def __init__(self, start_four):
        super().__init__()

        self.start_four = start_four
        self.painter = None
        self.pen = None
        pixmap = QtGui.QPixmap(800, 800)
        pixmap.fill(Qt.white)
        self.setPixmap(pixmap)
        self.setScaledContents(True)
        self.drawing()

    def drawing(self):
        self.painter = QtGui.QPainter(self.pixmap())
        self.pen = QtGui.QPen()
        self.pen.setWidth(5)

        Point = namedtuple("Point", "x y")
        start_point = Point(100, 100)
        p0, p1, p2, p3 = self.first_four_corners(start_point, width=600)
        num_locations = []
        colors = ["red", "orange", "green", "blue", "purple"]
        # start_four = [-9, 18, -5, 7]
        fours = self.find_fours(self.start_four)
        for count in range(5):
            color = colors[count]
            self.draw_square(p0, p1, p2, p3, color, fours[count])
            num_locations.append([p0, p1, p2, p3])
            p0, p1, p2, p3 = self.next_four_corners(p0, p1, p2, p3)

        self.painter.end()
        self.update()

    def draw_square(self, p0, p1, p2, p3, color, four_nums):
        # print(four_nums)
        self.pen.setColor(QtGui.QColor(color))
        self.painter.setPen(self.pen)
        self.painter.drawLines([
            QtCore.QLine(QPoint(*p0), QPoint(*p1)),
            QtCore.QLine(QPoint(*p1), QPoint(*p2)),
            QtCore.QLine(QPoint(*p2), QPoint(*p3)),
            QtCore.QLine(QPoint(*p3), QPoint(*p0)),
        ])

        brush = QtGui.QBrush()
        num_color_bg = QtGui.QColor(color)
        num_color_bg.setAlpha(120)

        brush.setStyle(Qt.SolidPattern)
        font = QtGui.QFont()
        font.setFamily("Consolas")
        font.setBold(True)
        num_font_size = 10
        font.setPointSize(num_font_size)
        self.painter.setFont(font)

        for i, p in enumerate([p0, p1, p2, p3]):
            # draw circles
            brush.setColor(QtGui.QColor("white"))
            self.painter.setBrush(brush)
            self.painter.drawEllipse(QtCore.QPoint(p.x, p.y), 40, 40)
            brush.setColor(num_color_bg)
            self.painter.setBrush(brush)
            self.painter.drawEllipse(QtCore.QPoint(p.x, p.y), 40, 40)

            self.pen.setColor(QtGui.QColor("black"))
            self.painter.setPen(self.pen)
            num_str = str(four_nums[i])
            xoffset = num_font_size * len(num_str) - num_font_size//2
            yoffset = num_font_size
            self.painter.drawText(p.x-xoffset, p.y + yoffset, num_str)

    def first_four_corners(self, top_left_point, width):
        Point = namedtuple("Point", "x y", defaults=[0, 0])
        p0 = top_left_point
        p1 = Point(p0.x + width, p0.y)
        p2 = Point(p1.x, p1.y + width)
        p3 = Point(p0.x, p0.y+width)
        return p0, p1, p2, p3

    def next_four_corners(self, p0, p1, p2, p3):
        Point = namedtuple("Point", "x y", defaults=[0, 0])
        n0 = Point((p0.x+p1.x)//2, (p0.y+p1.y)//2)
        n1 = Point((p1.x+p2.x)//2, (p1.y+p2.y)//2)
        n2 = Point((p2.x+p3.x)//2, (p2.y+p3.y)//2)
        n3 = Point((p3.x+p0.x)//2, (p3.y+p0.y)//2)
        return n0, n1, n2, n3

    def find_fours(self, start_four):
        f0, f1, f2, f3 = start_four
        fours = []
        fours.append(start_four)
        for _ in range(4):
            fours.append([abs(f0-f1), abs(f1-f2), abs(f2-f3), abs(f3-f0)])
            f0, f1, f2, f3 = abs(f0 - f1), abs(f1 - f2), abs(f2 - f3), abs(f3 - f0)
        return fours


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, start_four):
        super().__init__()

        self.widget = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout()
        self.widget.setLayout(layout)

        self.start_four = start_four
        canvas = Canvas(start_four)
        layout.addWidget(canvas)

        self.input_btn = QtWidgets.QPushButton("Update")
        self.input_btn.clicked.connect(self.button_click)

        self.input_label = QtWidgets.QLabel("Enter four numbers:")
        self.input_num0 = QtWidgets.QLineEdit()
        self.input_num1 = QtWidgets.QLineEdit()
        self.input_num2 = QtWidgets.QLineEdit()
        self.input_num3 = QtWidgets.QLineEdit()
        self.input_num0.setText("10")
        self.input_num1.setText("10")
        self.input_num2.setText("10")
        self.input_num3.setText("10")

        input_layout = self.get_input_layout()
        layout.addLayout(input_layout)

        self.setCentralWidget(self.widget)

    def get_input_layout(self):
        input_layout = QtWidgets.QHBoxLayout()
        input_layout.addWidget(self.input_label)
        input_layout.addWidget(self.input_num0)
        input_layout.addWidget(self.input_num1)
        input_layout.addWidget(self.input_num2)
        input_layout.addWidget(self.input_num3)
        input_layout.addWidget(self.input_btn)
        return input_layout

    def button_click(self):
        num0 = int(self.input_num0.text())
        num1 = int(self.input_num1.text())
        num2 = int(self.input_num2.text())
        num3 = int(self.input_num3.text())
        self.start_four = [num0, num1, num2, num3]

        self.widget = QtWidgets.QWidget()
        layout = QtWidgets.QVBoxLayout()
        self.widget.setLayout(layout)

        canvas = Canvas(self.start_four)
        layout.addWidget(canvas)

        input_layout = self.get_input_layout()
        layout.addLayout(input_layout)

        self.setCentralWidget(self.widget)
        # print(self.start_four)


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow(start_four=[12, 5, 18, 27])
    window.resize(800, 1000)
    window.setWindowTitle("Diffy!")
    window.show()
    app.exec_()
...