pyqt5rotationqgraphicsviewqgraphicssceneqgraphicswidget

I would like to rotate a widget using QGraphicsScene in PyQt (QLineEdit and QPushButton)


I would like to rotate a widget in pyqt5, I have developed this code but it doesn't work. The angle doesn't update and it returns a False. Do anyone know how to update this angle to make the widget rotate? If someone can help, thank you.

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

import sys

robotx=200
roboty=100

class MainWindow(QMainWindow):

    def __init__(self):

        super().__init__()

        self.setWindowTitle("My Awesome Rotating Widget")
        self.setGeometry(0, 0, 640, 480)

        self.R=Robot()

        self.angle=0

        self.AngleLineEdit=QLineEdit(self)
        self.AngleLineEdit.setGeometry(50,50,160,35)
        self.AngleLineEdit.setStyleSheet("background-color: rgba(50,50,50,20); color:black; font-weight: bold; font-size: 8pt; font-family: Helvetica; border-radius:5px;")

        self.AcceptButton=QPushButton(self)
        self.AcceptButton.setText("Accept")
        self.AcceptButton.setGeometry(50,100,160,35)
        self.AcceptButton.setStyleSheet("QPushButton{color:black; font-weight: bold; font-size: 8pt; font-family: Helvetica; background-color:rgb(255,255,255,20); border-radius:5px}""QPushButton:hover{background-color : rgb(255,255,255,100);}")

        container = RotatableContainer(self,self.R, 0)
        container.move(robotx,roboty)
        container.resize(150,150)
        container.setStyleSheet("background-color:transparent;")

        self.AcceptButton.clicked.connect(lambda: self.RotateWidget())
        self.AcceptButton.clicked.connect(container.rotate)

        self.show()

    def RotateWidget(self):

        self.angle=int(self.AngleLineEdit.text())
        print(self.angle)


class RotatableContainer(QGraphicsView):

    def __init__(self, parent, widget, angle):

        super().__init__(parent)

        scene = QGraphicsScene(self)
        self.setScene(scene)

        self.proxy = QGraphicsProxyWidget()
        self.proxy.setWidget(widget)
        self.proxy.setTransformOriginPoint(self.proxy.boundingRect().center())
        self.proxy.setRotation(angle)
        scene.addItem(self.proxy)

    def rotate(self, angle):

        print(angle)

        self.proxy.setRotation(angle)



class Robot(QWidget):
    
    def __init__(self):

        super().__init__()
        self.setGeometry(0,0,100,100)        

    def paintEvent(self, event):

        p=QPainter(self)
        r=QRect(0,0,99,99)
        c=QColor(0,0,0)
        p.setBrush(QBrush(c))
        p.drawRect(r)


app = QApplication([])
window = MainWindow()
app.exec_()

I have seen an example of how to rotate a widget using a qslider but I don't know how to adapt it using a QLineEdit and a QPushButton.


Solution

  • The first argument of clicked is always its check state, which by default is False for non checkable/checked buttons.

    Since you've connected the signal to the rotate function, the argument is that of the button signal, and since False also means 0, you're practically doing self.proxy.setRotation(0).

    Set the container as an instance attribute and call its rotate function from there:

    class MainWindow(QMainWindow):
    
        def __init__(self):
            # ...
            self.container = RotatableContainer(self,self.R, 0)
            self.container.move(robotx,roboty)
            self.container.resize(150,150)
            self.container.setStyleSheet("background-color:transparent;")
    
            self.AcceptButton.clicked.connect(self.RotateWidget)
    
            self.show()
    
        def RotateWidget(self):
    
            angle = self.AngleLineEdit.text()
            if angle.isdigit():
                self.angle = angle
    
            self.container.rotate(self.angle)
    

    Note: you should always use layout managers, and only classes and constants should have capitalized names (see the Style Guide for Python Code).