I experiencing some issue while trying to understand how animate a qgraphicItem in Pyqt.
I'm trying to animate a qgraphicsItem inside a scene, but when the animation starts all the objects rotate. Is there someone who can help me?
here is my code.
from PyQt6.QtGui import *
from PyQt6.QtCore import *
from PyQt6.QtWidgets import *
class GraphicsView(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.setRenderHints(QPainter.RenderHint.Antialiasing
| QPainter.RenderHint.TextAntialiasing | QPainter.RenderHint.SmoothPixmapTransform)
self.setViewportUpdateMode(QGraphicsView.ViewportUpdateMode.FullViewportUpdate)
self.scene = QGraphicsScene(QRectF(-250, -250, 1000, 1000), self)
self.setScene(self.scene)
self.graphicItem = QGraphicsRectItem(0, 0, 100, 100)
self.graphicItem.setZValue(10)
self.graphicItem.setPos(100, 100)
self.scene.addItem(self.graphicItem)
self.scene.addRect(self.sceneRect(), brush=QBrush(Qt.GlobalColor.gray))
self.animateRotation()
def rot(self, angle: QVariant) -> None:
self.rotate(self.graphicItem.rotation() - angle)
self.graphicItem.setRotation(angle)
#pyqtSlot()
def animateRotation(self):
self.animation = QVariantAnimation(self)
self.animation.setStartValue(QVariant(0))
self.animation.setEndValue(QVariant(180))
self.animation.setDuration(10000)
self.animation.start()
self.animation.valueChanged.connect(self.rot)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = GraphicsView()
w.resize(720, 720)
w.show()
sys.exit(app.exec())
Related
The current value could displayed immediately above the slider,such like this:
enter image description here
Thanks so much!
I had try like it but it show not good enough.
Here is my codes:
import sys
from PySide2.QtWidgets import QApplication, QWidget, QSlider, QLabel
from PySide2.QtCore import Qt
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.slider = QSlider(Qt.Horizontal, self)
self.slider.setRange(0, 100)
self.slider.setValue(50)
self.slider.setGeometry(30, 40, 100, 30)
self.slider.valueChanged[int].connect(self.changeValue)
self.label = QLabel(self)
self.label.setText("50")
self.label.setGeometry(140, 40, 30, 30)
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('QSlider')
self.show()
def changeValue(self, value):
self.label.setText(str(value))
self.label.move(self.slider.x() + value, self.slider.y() - 20)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
sys.exit(app.exec_())
I'm trying to make pyqt5 Gui that shows a webcam live feed, records the feed at the same time, and saves it locally when closed. I managed to acheieve this using Timer(QTimer) in pyqt gui but When I try to implement it using Qthread (Which I really require) only the live feed is working.
Whenever I add Code required for recording video and run the program it says Python has Stopped Working and closes. Here is my Code:
import cv2
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QVBoxLayout
from PyQt5.QtCore import QThread, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QImage, QPixmap
class Thread(QThread):
changePixmap = pyqtSignal(QImage)
def run(self):
self.cap = cv2.VideoCapture(0)
self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
self.codec = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
self.writer = cv2.VideoWriter('output.avi', self.codec, 30.0, (self.width, self.height))
while self.cap.isOpened():
ret, self.frame = self.cap.read()
if ret:
self.frame = cv2.flip(self.frame, 1)
rgbimage = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgbimage.shape
bytesPerLine = ch * w
convertToQtFormat = QImage(rgbimage.data, w, h, bytesPerLine, QImage.Format_RGB888)
p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
self.changePixmap.emit(p)
class MyApp(QWidget):
def __init__(self):
super(MyApp, self).__init__()
self.title = 'Camera'
self.initUI()
def initUI(self):
self.label = QLabel(self)
lay = QVBoxLayout()
lay.addWidget(self.label)
self.setLayout(lay)
self.th = Thread()
self.th.changePixmap.connect(self.setImage)
self.th.start()
self.show()
#pyqtSlot(QImage)
def setImage(self, image):
self.label.setPixmap(QPixmap.fromImage(image))
self.th.writer.write(image)
def main():
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I tried placing the .write() inside the run() of Thread class as well which is showing the same error. Can you guys point out What I'm doing wrong and how to make it work. I'm new to python and pyqt.
Thanks in Advance.
You need to separate threads. First thread is for signal, second is for the record and the main thread is for GUI. Try the following code. There is a button to start/stop the record.
import sys
import cv2
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, pyqtSlot
from PyQt5 import QtWidgets, QtCore, QtGui
#https://ru.stackoverflow.com/a/1150993/396441
class Thread1(QThread):
changePixmap = pyqtSignal(QImage)
def __init__(self, *args, **kwargs):
super().__init__()
def run(self):
self.cap1 = cv2.VideoCapture(0, cv2.CAP_DSHOW)
self.cap1.set(3,480)
self.cap1.set(4,640)
self.cap1.set(5,30)
while True:
ret1, image1 = self.cap1.read()
if ret1:
im1 = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB)
height1, width1, channel1 = im1.shape
step1 = channel1 * width1
qImg1 = QImage(im1.data, width1, height1, step1, QImage.Format_RGB888)
self.changePixmap.emit(qImg1)
class Thread2(QThread):
def __init__(self, *args, **kwargs):
super().__init__()
self.active = True
def run(self):
if self.active:
self.fourcc = cv2.VideoWriter_fourcc(*'XVID')
self.out1 = cv2.VideoWriter('output.avi', self.fourcc, 30, (640,480))
self.cap1 = cv2.VideoCapture(0, cv2.CAP_DSHOW)
self.cap1.set(3, 480)
self.cap1.set(4, 640)
self.cap1.set(5, 30)
while self.active:
ret1, image1 = self.cap1.read()
if ret1:
self.out1.write(image1)
self.msleep(10)
def stop(self):
self.out1.release()
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(660, 520)
self.control_bt = QPushButton('START')
self.control_bt.clicked.connect(self.controlTimer)
self.image_label = QLabel()
self.saveTimer = QTimer()
self.th1 = Thread1(self)
self.th1.changePixmap.connect(self.setImage)
self.th1.start()
vlayout = QVBoxLayout(self)
vlayout.addWidget(self.image_label)
vlayout.addWidget(self.control_bt)
#QtCore.pyqtSlot(QImage)
def setImage(self, qImg1):
self.image_label.setPixmap(QPixmap.fromImage(qImg1))
def controlTimer(self):
if not self.saveTimer.isActive():
# write video
self.saveTimer.start()
self.th2 = Thread2(self)
self.th2.active = True
self.th2.start()
# update control_bt text
self.control_bt.setText("STOP")
else:
# stop writing
self.saveTimer.stop()
self.th2.active = False
self.th2.stop()
self.th2.terminate()
# update control_bt text
self.control_bt.setText("START")
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
you placed the .write() inside the run() of Thread class is right way.
like:
...
while self.cap.isOpened():
ret, self.frame = self.cap.read()
if ret:
self.frame = cv2.flip(self.frame, 1)
rgbimage = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgbimage.shape
bytesPerLine = ch * w
convertToQtFormat = QImage(
rgbimage.data, w, h, bytesPerLine, QImage.Format_RGB888)
p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
# put your writer() here, make sure your param is frame
# not converted to QtImage format
self.writer.write(rgbimage)
self.changePixmap.emit(p)
...
I'm trying to render my image, but scaled to the height of the current window and keeping with aspect ratio.
The following does just that, but does not actually scale the image:
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Img(QWidget):
def __init__(self, parent=None):
super(Img, self).__init__(parent)
self.setAttribute(Qt.WA_StyledBackground, True)
self.setStyleSheet('background-color: orange')
window = QDesktopWidget().screenGeometry(0)
height = window.height()
layout = QVBoxLayout(self)
pixmap = QPixmap("test.png")
pixmap = pixmap.scaledToHeight(height)
label = QLabel()
label.setPixmap(pixmap)
label.setScaledContents(True)
layout.addWidget(label)
print(height)
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
img = Img()
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(img)
layout.setAlignment(Qt.AlignCenter)
content = QWidget()
content.setLayout(layout)
w,h = (1024,670)
self.resize(w,h)
self.setCentralWidget(content)
self.show()
if __name__ == '__main__':
app = QApplication([])
window = MainWindow()
app.exec_()
Although it prints out height is 1050, what I see is a huge image and the window expands down past my monitor. Can someone explain the issue and what needs to happen for scaledToHeight()?
Here is an example of what I see:
And here is the actual image:
The image gets cut off because it gets extended past the monitor screen, and is also stretched oddly.
I'm writing a widget that should have a transparent background.
Unfortunately, I get a black background instead of transparent.
I've used attributes like:
WA_TranslucentBackground
WA_NoSystemBackground
and also flags:
Qt.FramelessWindowHint
Qt.X11BypassWindowManagerHint
my system using KWin windows manager which is based on x.org
Here's a quick example of my widget:
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
import sys
from psutil import cpu_percent
class MyWidget(QWidget):
def __init__(self, parent=None):
super().__init__()
self.resize(600, 600)
self.dark = "#3B3A44"
self.light = "#4a4953"
self.color = "#75ECB5"
self.setAttribute(Qt.WA_TranslucentBackground, True)
self.setAttribute(Qt.WA_NoSystemBackground, True)
self.setStyleSheet("background:transparent;")
# self.setAttribute(QtCore.Qt.WA_PaintOnScreen)
self.setWindowFlags(Qt.FramelessWindowHint |
Qt.X11BypassWindowManagerHint |
Qt.Tool)
def paintEvent(self, event: QPaintEvent):
""" Dessine l'horloge """
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
base_rect = self.rect().adjusted(20, 20, -20, -20)
painter.setBrush(QBrush(QColor(self.dark)))
painter.drawEllipse(base_rect)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.move(800, 300)
w.show()
app.exec_()
Check if translucency is enable on your KDE systemsettings.
Also you can install other tools like xcompmgr and execute it before starting your app.
I wnat to hide my label and button when someone is pushing a button but i have the problem in my code that i dont can acces the label variable and that i dont know how to hide maybe it works with this code?:
setStyleSheet("display: none;")
And here is my code that doesnt work whe i push the button the python programm say no respond
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import QtWidgets
class WindowInhalt(QWidget):
def label(self):
label1 = QtWidgets.QLabel(self)
label1.setText("Überschrift mit namen des text adventure")
label1.setStyleSheet("font-size: 18px;color: black;")
label1.setGeometry(50, 50, 400, 100)
label1.move(350, 50)
label2 = QtWidgets.QLabel(self)
label2.setText("Spielen")
label2.setStyleSheet("font-size: 18px;color: black;")
label2.setGeometry(50, 50, 400, 100)
label2.move(450, 120)
label2.mousePressEvent = self.spielen
label3 = QtWidgets.QLabel(self)
label3.setText("Settings")
label3.setStyleSheet("font-size: 18px;color: black;")
label3.setGeometry(50, 50, 400, 100)
label3.move(450, 200)
label3.mousePressEvent = self.settings
label4 = QtWidgets.QLabel(self)
label4.setText("Credits")
label4.setStyleSheet("font-size: 18px;color: black;")
label4.setGeometry(50, 50, 400, 100)
label4.move(450, 280)
label4.mousePressEvent = self.credits
def Button(self):
QToolTip.setFont(QFont("Arial", 10))
button = QPushButton("Spiel beenden", self)
button.setGeometry(50, 50, 150, 50)
button.setFont(QFont("Arial", 12))
button.move(820, 420)
button.setToolTip("<b>Button lel</b>")
button.clicked.connect(QtCore.QCoreApplication.instance().quit)
button.clicked.connect(self.gedruekt)
button.setStyleSheet("background-color: white;")
class Window(WindowInhalt):
def __init__(self):
super().__init__()
self.initMe()
def initMe(self):
WindowInhalt.Button(self)
WindowInhalt.label(self)
self.setGeometry(50,50,1000,500)
self.setWindowTitle("Gui lalal einhorn")
self.setWindowIcon(QIcon("cookie.png"))
self.setAutoFillBackground(True)
self.setStyleSheet("background-color: lightblue;")
self.move(500, 250)
self.show()
def spielen(self, event,):
print("spielen")
WindowInhalt.label.label2.setStyleSheet("display:none;")
#here i want to hide the label
def settings(self, event):
print("settings")
def credits(self, event):
print("credits")
def gedruekt(self, event):
print("Er hats getan ;(")
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Window()
sys.exit(app.exec_())
else:
print("Gui not created, because script used at liabary")
maybe somone can help me.
EDIT1:
when i do it so
def spielen(self, event,):
print("spielen")
self.label1 = QtWidgets.QLabel(self)
self.label1.hide()
than i get in the console the message spielen but the label is still there
when i do it so:
def spielen(self, event,):
print("spielen")
self.label1.hide()
than the programm crasht
EDIT2:
For anyone who is instredtef above the right code her he is:
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import QtWidgets
class WindowInhalt(QWidget):
def label(self):
self.label1 = QtWidgets.QLabel(self)
self.label1.setText("Überschrift mit namen des text adventure")
self.label1.setStyleSheet("font-size: 18px;color: black;")
self.label1.setGeometry(50, 50, 400, 100)
self.label1.move(350, 50)
self.label1.show()
self.label2 = QtWidgets.QLabel(self)
self.label2.setText("Spielen")
self.label2.setStyleSheet("font-size: 18px;color: black;")
self.label2.setGeometry(50, 50, 400, 100)
self.label2.move(450, 120)
self.label2.mousePressEvent = self.spielen
self.label2.show()
self.label3 = QtWidgets.QLabel(self)
self.label3.setText("Settings")
self.label3.setStyleSheet("font-size: 18px;color: black;")
self.label3.setGeometry(50, 50, 400, 100)
self.label3.move(450, 200)
self.label3.mousePressEvent = self.settings
self.label3.show()
self.label4 = QtWidgets.QLabel(self)
self.label4.setText("Credits")
self.label4.setStyleSheet("font-size: 18px;color: black;")
self.label4.setGeometry(50, 50, 400, 100)
self.label4.move(450, 280)
self.label4.mousePressEvent = self.credits
self.label4.show()
def button(self):
QToolTip.setFont(QFont("Arial", 10))
self.button = QPushButton("Spiel beenden", self)
self.button.setGeometry(50, 50, 150, 50)
self.button.setFont(QFont("Arial", 12))
self.button.move(820, 420)
self.button.setToolTip("<b>Button lel</b>")
self.button.clicked.connect(QtCore.QCoreApplication.instance().quit)
self.button.clicked.connect(self.gedruekt)
self.button.setStyleSheet("background-color: white;")
self.button.show()
class Window(WindowInhalt):
def __init__(self):
super().__init__()
self.initMe()
def initMe(self):
self.label()
self.button()
self.setGeometry(50,50,1000,500)
self.setWindowTitle("Gui lalal einhorn")
self.setWindowIcon(QIcon("cookie.png"))
self.setAutoFillBackground(True)
self.setStyleSheet("background-color: lightblue;")
self.move(500, 250)
self.show()
def spielen(self, event,):
print("spielen")
self.label1.hide()
def settings(self, event):
print("settings")
def credits(self, event):
print("credits")
def gedruekt(self, event):
print("Er hats getan ;(")
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Window()
sys.exit(app.exec_())
else:
print("Gui not created, because script used at liabary")
If you want to refer to an object you've created inside a class, you need to declare it as an attribute of this class, with self.labelX:
self.label1 = QtWidgets.QLabel(self)
Then in any method of this class, you can easily call this attribute:
self.label1.hide()
or elsewhere in the code
window_inhalt_instance.label1.hide()
EDIT :
I focused on how you're instantiating the class, you need to change some parts here too:
The labels are not hidden because they are created with WindowInhalt.label(self)
As your class Window inherits from WindowInhalt, you can called directly
self.label() # in initme(), same for the buttons
But you need to change every labels declaration in WindowInhalt, by adding self