How can I make a circle bounce in a window? - python-3.x

I just made this program as a practice I want to make the circle bounce from end to end which I came up in this source codes can you make if happen.
import PyQt5,sys
from PyQt5 import QtCore,QtGui,QtWidgets
from PyQt5.QtCore import Qt,QTimer,QPoint
from PyQt5.QtWidgets import QWidget,QApplication,QMainWindow
from PyQt5.QtGui import QPainter
class Circle(QWidget):
def __init__(self):
QMainWindow.__init__(self)
self.resize(250,500)
self.setWindowTitle("Bounce-Man")
self.color = Qt.red
self.fixedplace = 125
self.mover = 450
def paintEvent(self,event):
bouncer.setPen(Qt.black)
bouncer.setBrush(self.color)
bouncer.drawEllipse(QPoint(self.fixedplace,self.mover),50,50)
#QtCore.pyqtSlot()
def timer(self):
timer = QTimer()
while self.mover >=50:
timer.start(1000)
if self.mover == 50:
self.mover = 450
self.mover -= 1
self.update()
if __name__ == "__main__":
window = QApplication(sys.argv)
app = Circle()
app.show()
sys.exit( window.exec_() )

You must use a QTimer to call a function that updates the position, do not use a while loop:
from PyQt5 import QtCore, QtGui, QtWidgets
class Circle(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Circle, self).__init__(parent)
self.resize(250,500)
self.setWindowTitle("Bounce-Man")
self.color = QtGui.QColor(QtCore.Qt.red)
self.rect_circle = QtCore.QRect(0, 0, 50, 50)
self.rect_circle.moveCenter(QtCore.QPoint(self.width()/2, self.rect_circle.height()/2))
self.step = QtCore.QPoint(0, 5)
self.y_direction = 1
timer = QtCore.QTimer(self, interval=30)
timer.timeout.connect(self.update_position)
timer.start()
def paintEvent(self,event):
bouncer = QtGui.QPainter(self)
bouncer.setPen(QtCore.Qt.black)
bouncer.setBrush(self.color)
bouncer.drawEllipse(self.rect_circle)
#QtCore.pyqtSlot()
def update_position(self):
if self.rect_circle.bottom() > self.height() and self.y_direction == 1:
self.y_direction = -1
if self.rect_circle.top() < 0 and self.y_direction == -1:
self.y_direction = 1
self.rect_circle.translate(self.step * self.y_direction)
self.update()
if __name__ == "__main__":
import sys
window = QtWidgets.QApplication(sys.argv)
app = Circle()
app.show()
sys.exit( window.exec_() )

Related

Window can't show max size after resize the window?

I create a simple window, when I resize the window to fixed size, and then I want to showMaximized, it had no effect? what happened in here?
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class Win(QPushButton):
def __init__(self):
super().__init__()
self.clicked.connect(self.onClick)
self.i = 0
def onClick(self):
self.i += 1
if self.i%2 == 1:
self.resize(100, 100)
else:
self.showMaximized()
# self.showMinimized()
self.update()
self.updateGeometry()
app = QApplication([])
win = Win()
win.show()
app.exec()

How to record the video from a webcam in a pyqt5 gui using OpenCV and QThread?

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)
...

How can I take a value from a line edit to another window's line edit by using Python and PyQt5?

What I need:
I need to create a simple project that can take value from window to another window
My research effort:
So, I create two classes for two windows then connect to classes with each other, so when I click in button it takes the value from 1st window then open the other window but the value=nothing because the clickMethod returns nothing.
Below is my code:
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QWidget, QLabel, QLineEdit
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtCore import QSize
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMinimumSize(QSize(320, 140))
self.setWindowTitle("First Window")
self.nameLabel = QLabel(self)
self.nameLabel.setText('1st:')
self.line = QLineEdit(self)
self.line.move(80, 20)
self.line.resize(200, 32)
self.nameLabel.move(20, 20)
pybutton = QPushButton('OK', self)
pybutton.clicked.connect(self.second_wind) #connect button to open second window
pybutton.clicked.connect(self.clickMethod)
pybutton.resize(200,32)
pybutton.move(80, 60)
def clickMethod(self):
value =self.line.text() #take value from the line edit
return value
def second_wind(self): #object from secod_window class
self.SW = Second_Window()
self.SW.show()
class Second_Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMinimumSize(QSize(320, 140))
self.setWindowTitle("Second Window")
self.nameLabel = QLabel(self)
self.nameLabel.setText('Name:')
self.line = QLineEdit(self)
self.line.move(80, 20)
self.line.resize(200, 32)
self.nameLabel.move(20, 20)
self.f = MainWindow() #make object from MainWindow class to execute clickMethod() to reutrn value
a=self.f.clickMethod()
print(a)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit( app.exec_() )
I expect the Clickmethod to return the value
but it returns nothing
Try it:
import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QWidget, QLabel, QLineEdit
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtCore import QSize
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMinimumSize(QSize(320, 140))
self.setWindowTitle("First Window")
self.nameLabel = QLabel(self)
self.nameLabel.setText('1st:')
self.line = QLineEdit(self)
self.line.move(80, 20)
self.line.resize(200, 32)
self.nameLabel.move(20, 20)
pybutton = QPushButton('OK', self)
pybutton.clicked.connect(self.second_wind)
# pybutton.clicked.connect(self.clickMethod)
pybutton.resize(200,32)
pybutton.move(80, 60)
# def clickMethod(self):
# value =self.line.text()
# return value
def second_wind(self):
text = self.line.text() # +++
self.SW = Second_Window(text) # +++ (text)
self.SW.show()
class Second_Window(QMainWindow):
def __init__(self, text): # +++ (text)
QMainWindow.__init__(self)
self.text = text # +
self.setMinimumSize(QSize(320, 140))
self.setWindowTitle("Second Window")
self.nameLabel = QLabel(self)
self.nameLabel.setText('Name:')
self.line = QLineEdit(self)
self.line.move(80, 20)
self.line.resize(200, 32)
self.nameLabel.move(20, 20)
# self.f = MainWindow()
# a=self.f.clickMethod()
self.line.setText(self.text) # +
print(self.text)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit( app.exec_() )

Slider in PyQt4

I am new to PyQt, I am trying to implement slider in PyQt4, but i don't know why code code is not generating any output.
what i want is, create 3 slider to change 3 values dynamically.
Here i am resizing font size of text "hue", "sat", "val".
Is there is any good source to learn slider in PyQt?
here is my code
PyQt4Slider.py
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50,50,500,300)
self.setWindowTiltle("HSV")
self.home()
def home(self):
#hue = 100
#sat = 100
#val = 100
layout = QVBoxLayout()
self.l1 = QLabel("hue")
self.l2 = QLabel("sat")
self.l3 = QLabel("val")
self.l1.setAlignment(Qt.AlignCenter)
self.l2.setAlignment(Qt.AlignCenter)
self.l3.setAlignment(Qt.AlignCenter)
layout.addWidget(self.l1)
layout.addWidget(self.l1)
layout.addWidget(self.l1)
self.sl = QSlider(Qt.Horizontal)
self.s2 = QSlider(Qt.Horizontal)
self.s3 = QSlider(Qt.Horizontal)
self.sl.setMinimum(0)
self.sl.setMaximum(179)
self.sl.setValue(20)
self.sl.setTickPosition(QSlider.TicksBelow)
self.sl.setTickInterval(5)
self.s2.setMinimum(0)
self.s2.setMaximum(255)
self.s2.setValue(100)
self.s2.setTickPosition(QSlider.TicksBelow)
self.s2.setTickInterval(5)
self.s3.setMinimum(0)
self.s3.setMaximum(255)
self.s3.setValue(100)
self.s3.setTickPosition(QSlider.TicksBelow)
self.s3.setTickInterval(5)
layout.addWidget(self.s1)
self.sl.valueChanged.connect(self.valuechange)
layout.addWidget(self.s2)
self.s2.valueChanged.connect(self.valuechange)
layout.addWidget(self.s3)
self.s3.valueChanged.connect(self.valuechange)
self.setLayout(layout)
def valuechange(self):
sizel1 = self.sl.value()
self.l1.setFont("Arial",sizel1)
sizel2 = self.sl.value()
self.l2.setFont("Arial", sizel2)
sizel2 = self.sl.value()
self.l2.setFont("Arial", sizel2)
def main():
app = QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
here is what i am getting after running code
Ran 0 tests in 0.000s
OK
Process finished with exit code 0
Empty test suite.
Most of the problems in your script are caused by typos. Here is a fixed version that should work okay:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50,50,500,300)
self.setWindowTitle("HSV")
self.home()
def home(self):
layout = QVBoxLayout()
self.l1 = QLabel("hue")
self.l2 = QLabel("sat")
self.l3 = QLabel("val")
self.l1.setAlignment(Qt.AlignCenter)
self.l2.setAlignment(Qt.AlignCenter)
self.l3.setAlignment(Qt.AlignCenter)
layout.addWidget(self.l1)
layout.addWidget(self.l2)
layout.addWidget(self.l3)
self.s1 = QSlider(Qt.Horizontal)
self.s2 = QSlider(Qt.Horizontal)
self.s3 = QSlider(Qt.Horizontal)
self.s1.setMinimum(0)
self.s1.setMaximum(179)
self.s1.setValue(20)
self.s1.setTickPosition(QSlider.TicksBelow)
self.s1.setTickInterval(5)
self.s2.setMinimum(0)
self.s2.setMaximum(255)
self.s2.setValue(100)
self.s2.setTickPosition(QSlider.TicksBelow)
self.s2.setTickInterval(5)
self.s3.setMinimum(0)
self.s3.setMaximum(255)
self.s3.setValue(100)
self.s3.setTickPosition(QSlider.TicksBelow)
self.s3.setTickInterval(5)
layout.addWidget(self.s1)
self.s1.valueChanged.connect(self.valuechange)
layout.addWidget(self.s2)
self.s2.valueChanged.connect(self.valuechange)
layout.addWidget(self.s3)
self.s3.valueChanged.connect(self.valuechange)
self.setLayout(layout)
# set the initial fonts
self.valuechange()
def valuechange(self):
sizel1 = self.s1.value()
self.l1.setFont(QFont("Arial", sizel1))
sizel2 = self.s2.value()
self.l2.setFont(QFont("Arial", sizel2))
sizel3 = self.s3.value()
self.l3.setFont(QFont("Arial", sizel3))
def main():
app = QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

QWidget cannot display on QMainWindow instance PyQt5

I am learning PyQt5 now and tried to do something little on my own. I have made a very basic custom toolbox, which has just 6 QPushButtons buttons on it, which inherits from QWidget class.
My problem is that I can't display my toolbox on my QMainWidow instance. Let me show you what I did;
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class ToolBox(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
btn = [QPushButton('B', self) for i in range(6)]
for Btn in btn:
Btn.resize(30, 30)
self.resize(60, 90)
k = 0
for i in range(6):
btn[i].move((i%2)*30, k*30)
k += 1 if i % 2 == 1 else 0
self.show()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(300, 200)
self.statusBar().showMessage('Ready!')
exitAction = QAction(QIcon('idea.png'), 'Exit', self)
exitAction.setStatusTip('Exit application')
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(qApp.quit)
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('File')
fileMenu.addAction(exitAction)
t = ToolBox()
t.move(150, 150)
t.show() #With and without this line, it doesn't work.
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
m = MainWindow()
sys.exit(app.exec_())
You just need to position your widget somewhere in the QMainWindow canvas. All you have to do is position it in the MainWindow. Just for an example, I use setCentralWidget() to position your QWidget.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class ToolBox(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
btn = [QPushButton('B', self) for i in range(6)]
for Btn in btn:
Btn.resize(30, 30)
self.resize(60, 90)
k = 0
for i in range(6):
btn[i].move((i%2)*30, k*30)
k += 1 if i % 2 == 1 else 0
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(300, 200)
self.statusBar().showMessage('Ready!')
exitAction = QAction(QIcon('idea.png'), 'Exit', self)
exitAction.setStatusTip('Exit application')
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(qApp.quit)
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('File')
fileMenu.addAction(exitAction)
t = ToolBox()
self.setCentralWidget(t)
if __name__ == '__main__':
app = QApplication(sys.argv)
m = MainWindow()
m.show()
sys.exit(app.exec_())

Resources