How to create multiple QLabels in a gui on PyQt5? - python

I've created a gui using PyQt5 in PyCharm and I've managed to get one QLabel with an image in it (Picture1.png) showing up, however, when I try to add a second QLabel with a second image (named Shutter1.png) on the same window, it seems to remove both labels and nothing shows up on the gui. I'm not sure where I'm going wrong and any help would be greatly appreciated, I'm a novice! NB I've doublechecked the filepath for both imagePath and imagePath_1 are correct. See below for attached code:
from PyQt5 import uic, QtWidgets, QtGui, QtCore
import sys
import pkg_resources
import functions.initialisation as inits
import functions.Sig2Open as S2O
import functions.Sig2Close as S2C
class Ui(QtWidgets.QMainWindow):
def __init__(self):
super(Ui, self).__init__()
self.gui = uic.loadUi('Shuttergui.ui', self)
# Creates the path of the image
self.imagePath = "C:/........../Picture1.png"
self.label = QtWidgets.QLabel(self.gui)
self.image = QtGui.QImage(self.imagePath)
self.pixmapImage = QtGui.QPixmap.fromImage(self.image)
self.label.setPixmap(self.pixmapImage)
self.label.resize(self.width(), self.height())
self.label.move(60, 170)
self.imagePath = "C:/....../Shutter1.png"
# Create label that holds the image in imagePath
self.label_1 = QtWidgets.QLabel(self.gui)
self.image_1 = QtGui.QImage(self.imagePath)
self.pixmapImage_1 = QtGui.QPixmap.fromImage(self.image_1)
self.label_1.setPixmap(self.pixmapImage_1)
self.label_1.resize(self.width(), self.height())
self.label_1.move(60, 170)
self.gui.showMaximized()
# redirect closeevent func to main self rather than inside gui
self.gui.closeEvent = self.closeEvent
# Initialise shutter functions
inits.ardopenup(self)
inits.ardshutup(self)
self.gui.show()
def closeEvent(self, event):
import time
time.sleep(0.1)
print("main thread quitting")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setStyleSheet(pkg_resources.resource_stream(__name__, '/css/darktheme/style.css').read().decode())
window = Ui()
sys.exit(app.exec_())

Related

PyQt5 Button Clicked Not Working with Function [duplicate]

This question already has answers here:
Argument 1 has unexpected type 'NoneType'?
(2 answers)
Closed 1 year ago.
I am trying to use function when I clicked the button with below source codes:
from PySide2.QtWidgets import QApplication
from ui_interface import *
from Custom_Widgets.Widgets import *
from PyQt5.QtGui import QIcon
# from PyQt5.QtWidgets import *
from Custom_Widgets.Widgets import QCustomSlideMenu
import sys
class MainWindow(QMainWindow):
def __init__(self,parent = None):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
########################################################################
# APPLY JSON STYLESHEET
########################################################################
# self = QMainWindow class
# self.ui = Ui_MainWindow / user interface class
loadJsonStyle(self, self.ui)
########################################################################
self.show()
self.ui.pushButton_2.clicked.connect(self.my_text())
#pyqtSlot()
def on_button1(self):
print("Button #1")
def my_text(self):
index = 1
print("{0} button clicked".format(index))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
# app.setWindowIcon(QIcon(':/icons/home.ico'))
window.show()
sys.exit(app.exec_())
When I using like this:
self.ui.pushButton_2.clicked.connect(self.my_text())
When I clicked the button, does not show anything.
But if I use like this:
self.ui.pushButton_2.clicked.connect(lambda: self.my_text())
It works.
And Also when I use like this:
self.ui.pushButton_2.clicked.connect(self.on_button1())
it works.
But I dont understand why the first step does not working?
try this
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class Window(QMainWindow):
def __init__(self):
super().__init__()
# setting title
self.setWindowTitle("Python ")
# setting geometry
self.setGeometry(100, 100, 600, 400)
# calling method
self.UiComponents()
# showing all the widgets
self.show()
# method for widgets
def UiComponents(self):
# creating a push button
button = QPushButton("CLICK", self)
# setting geometry of button
button.setGeometry(200, 150, 100, 30)
# adding action to a button
button.clicked.connect(self.clickme)
# action method
def clickme(self):
print("pressed")
# create pyqt5 app
App = QApplication(sys.argv)
# create the instance of our Window
window = Window()
# start the app
sys.exit(App.exec())
is you're looking for this???

Pyqt5 - how to go back to hided Main Window from Secondary Window?

If I click Back from the second window, the program will just exit. How do I go back to mainwindow in this case? I assume I will need some more code in that clickMethodBack function.
import os
import PyQt5
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QWidget, QLabel, QPushButton
import time
from PyQt5.QtCore import QSize
class GUI_Window():
def __init__(self):
self.main_window()
return
def main_window(self):
app = PyQt5.QtWidgets.QApplication(sys.argv)
self.MainWindow = MainWindow_()
self.MainWindow.show()
app.exec_()
return
class MainWindow_(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.TestAButton = QPushButton("TestA", self)
self.TestAButton.clicked.connect(self.TestA_clickMethod)
self.TestAButton.move(20, 0)
self.CloseButton = QPushButton("Close", self)
self.CloseButton.clicked.connect(self.Close_clickMethod)
self.CloseButton.move(20, 40)
self.TestingA = TestA_MainWindow()
def TestA_clickMethod(self):
self.TestAButton.setEnabled(False)
time.sleep(0.2)
self.TestingA.show()
self.hide()
try:
if self.TestingA.back == True:
self.show()
except:
None
def Close_clickMethod(self):
self.Test_Choice = 'Exit'
self.close()
class TestA_MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setMinimumSize(QSize(980,700))
self.setWindowTitle("TestA")
self.Back_Button = False
self.closeButton = QPushButton("Close", self)
self.closeButton.clicked.connect(self.clickMethodClose)
self.returnButton = QPushButton("Back", self)
self.returnButton.clicked.connect(self.clickMethodBack)
self.returnButton.move(0,30)
def clickMethodClose(self):
self.Back_Button = False
self.close()
def clickMethodBack(self):
self.returnButton.setEnabled(False)
time.sleep(0.5)
self.back = True
self.close()
# Run if Script
if __name__ == "__main__":
main = GUI_Window() # Initialize GUI
Your code has two very important issues.
you're using a blocking function, time.sleep; Qt, as almost any UI toolkit, is event driven, which means that it has to be able to constantly receive and handle events (coming from the system or after user interaction): when something blocks the event queue, it completely freezes the whole program until that block releases control;
you're checking for the variable too soon: even assuming the sleep would work, you cannot know if the window is closed after that sleep timer has ended;
The solution is to use signals and slots. Since you need to know when the second window has been closed using the "back" button, create a custom signal for the second window that will be emitted whenever the function that is called by the button is closed.
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
central = QtWidgets.QWidget()
layout = QtWidgets.QHBoxLayout(central)
self.testButton = QtWidgets.QPushButton('Test A')
self.closeButton = QtWidgets.QPushButton('Close')
layout.addWidget(self.testButton)
layout.addWidget(self.closeButton)
self.setCentralWidget(central)
self.testButton.clicked.connect(self.launchWindow)
self.closeButton.clicked.connect(self.close)
def launchWindow(self):
self.test = TestA_MainWindow()
self.test.backSignal.connect(self.show)
self.hide()
self.test.show()
class TestA_MainWindow(QtWidgets.QWidget):
backSignal = QtCore.pyqtSignal()
def __init__(self):
super().__init__()
layout = QtWidgets.QHBoxLayout(self)
self.closeButton = QtWidgets.QPushButton('Close')
self.backButton = QtWidgets.QPushButton('Back')
layout.addWidget(self.closeButton)
layout.addWidget(self.backButton)
self.closeButton.clicked.connect(self.close)
self.backButton.clicked.connect(self.goBack)
def goBack(self):
self.close()
self.backSignal.emit()
def GUI_Window():
import sys
app = QtWidgets.QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
if __name__ == '__main__':
GUI_Window()
Notes:
I removed the GUI_Window class and made a function, as using a class for that is not really useful;
you should always prefer layout managers instead of setting manual geometries;
widgets should not be added to a QMainWindow as direct children, and a central widget should always be used (see the creation and use of central in the example); read more about it in the documentation;
only classes and constants should be capitalized, while variables, attributes and functions should always have names starting with a lowercase letter;

PyQt video frame update signal (Trigger function after each video frame)

I am creating a video player and I need to draw some polygons on top of it. I am using a QGraphicsScene to create this and I need to update the polygons on screen after each frame. I am currently using the QMediaPlayer paired up with a QGraphicsVideoItem to create this. The problem I am having is that the QMediaPlayer doesn't have a signal that activates on each frame. It has positionChanged(), but this only seems to trigger once every second.
I tried using QMovie since it does send updates on every frame, but it did not display anything. This is the code I used to implement this.
video_view = QGraphicsView()#view to hold video
video_item = QGraphicsVideoItem()#video item for scene
video_scene = QGraphicsScene()#scene for Qgraphics view
video_view.setScene(video_scene)
label = QLabel()
movie = QMovie(self.video_paths[index]) #contains file path
label.setMovie(movie)
video_scene.addWidget(label)
self.vlayout_main_video.addWidget(video_view)
The video file I am using is a .avi file and it is 72Mb large.
I would really appreciate it if somebody could point me in the right direction on how I could do this. I am currently using PyQt5.
Thank you
There are 2 options:
positionChanged is emited every second because the notifyInterval property of QMediaPlayer is set in that period. So you can change that property, for example to 60 ms.
from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia, QtMultimediaWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
self.video_view = QtWidgets.QGraphicsView(scene)
self.setCentralWidget(self.video_view)
self.player = QtMultimedia.QMediaPlayer(self, QtMultimedia.QMediaPlayer.VideoSurface)
self.video_item = QtMultimediaWidgets.QGraphicsVideoItem()
self.player.setVideoOutput(self.video_item)
scene.addItem(self.video_item)
file = "/path/of/video"
self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file)))
self.player.positionChanged.connect(self.on_positionChanged)
self.player.setNotifyInterval(60)
self.player.play()
#QtCore.pyqtSlot('qint64')
def on_positionChanged(self, p):
print(p, QtCore.QTime.currentTime().toString("hh:mm:ss.zzz"))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
Use the VideoFrameProbed signal from QVideoProbe:
from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia, QtMultimediaWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
self.video_view = QtWidgets.QGraphicsView(scene)
self.setCentralWidget(self.video_view)
self.player = QtMultimedia.QMediaPlayer(self, QtMultimedia.QMediaPlayer.VideoSurface)
self.video_item = QtMultimediaWidgets.QGraphicsVideoItem()
self.player.setVideoOutput(self.video_item)
scene.addItem(self.video_item)
file = "/path/of/video"
self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file)))
self.player.play()
probe = QtMultimedia.QVideoProbe(self)
probe.videoFrameProbed.connect(self.on_videoFrameProbed)
probe.setSource(self.player)
#QtCore.pyqtSlot()
def on_videoFrameProbed(self):
print(QtCore.QTime.currentTime().toString("hh:mm:ss.zzz"))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())

pyqt5 calling function does not give same results

I am trying to develop a GUI to show my robot and obstacles around it. I created a class GUI and it has a member function showObstacle to show obstacle. Since I want to keep all the obstacles in place, I create new obstacle object in a vector to store all the objects.
I called this function in class's init function to test and it was successful.
But when I call this function in different class, it doesn't show the obstacles on the GUI window. In class TCP_Connection (where I get information about the robot), I created myGui class and I called showObstacle function.
After debugging, it turns out it creates the Obstacle Objects whenever it is called, but it doesn't display it on the window
#this is file 1, GUI Class
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtCore import Qt
from pynput import keyboard
class App(QWidget):
def __init__(self, OtherWindow):
super().__init__()
self.setGeometry(100,100,440,800)
self.setWindowTitle("New GUI Interface Window")
self.currentState = 0
self.obstCounter = 0
self.d = []
#testing showObstacle
self.showObstacle(205, 305) #this works
self.showObstacle(210,315) #this also works
self.show()
def showObstacle(self, Obs_x, Obs_y):
self.obstImage = QtGui.QImage('obsta_edited.png')
self.pixmap_obst = QtGui.QPixmap(self.obstImage)
self.d.append("O{0}".format(self.obstCounter))
self.d[self.obstCounter] = QtWidgets.QLabel(self)
self.d[self.obstCounter].setPixmap(self.pixmap_obst)
self.d[self.obstCounter].move(Obs_x, Obs_y)
self.d[self.obstCounter].adjustSize()
self.obstCounter += 1
print(self.d)
print("Obstacle Run")
this is the calling class
from myGUI import App
from PyQt5.QtWidgets import QWidget,QLabel,QLineEdit, QHBoxLayout,QVBoxLayout,QMainWindow,QPushButton, QFrame, QDesktopWidget, QApplication
from PyQt5.Qt import QStackedLayout
import sys, random
class TCP_Communication:
def __init__(self):
super().__init__()
self.openWindow()
def openWindow(self):
self.window = QMainWindow()
self.myGui = App(self.window)
self.myGui.showObstacle(215, 320)
self.stacked_layout = QStackedLayout()
self.stacked_layout.addWidget(self.myGui)
def tcp_showObstacle(self,x,y):
self.myGui.showObstacle(x,y)
if __name__ == '__main__':
app = QApplication([])
tcp_com = TCP_Communication()
sys.exit(app.exec_())
Edited : attached the result ; Suppose to show 4 obstacles but only shows 2
Edited2 : Code is executable now
The problem is that the QLabels are not showing, the main widget when displayed at the beginning makes your children show up, but after that it does not make them visible, as it is in your case, so your task is to call their method show() directly:
def showObstacle(self, Obs_x, Obs_y):
pixmap_obst = QtGui.QPixmap('obsta_edited.png')
self.d.append("O{0}".format(self.obstCounter))
label = QtWidgets.QLabel(self)
label.setPixmap(pixmap_obst)
label.move(Obs_x, Obs_y)
label.adjustSize()
label.show() # <---show QLabel
self.d[self.obstCounter] = label
self.obstCounter += 1
print(self.d)
print("Obstacle Run")

pyQT4 py3 Can't display image in QFrame background

I am trying since a little while to simply display an image in background of a QFrame and simply can't. I can see loads of example on the net but none of them seems to work with my code, and I can't understand why :
import sys, random
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QPalette, QBrush, QPixmap
class MainWin(QtGui.QMainWindow):
def __init__(self):
super(MainWin, self).__init__()
self.initUI()
def initUI(self):
#central widget
self.theboard = Board(self)
self.setCentralWidget(self.theboard)
self.resize(360, 760)
self.setWindowTitle('Name')
self.show()
class Board(QtGui.QFrame):
def __init__(self, parent):
super(Board, self).__init__(parent)
self.initBoard()
def initBoard(self):
print("ddd")
frame = Board
palette = QPalette(self)
palette.setBrush(QPalette.Background,QBrush(QPixmap("ImageTest.jpg")))
frame.setPalette(palette)
def main():
app = QtGui.QApplication([])
mw = MainWin()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
will return:
TypeError: QWidget.setPalette(QPalette): first argument of unbound method must have type 'QWidget'
If I don't pass my QFrame in a variable and do as such :
palette = QPalette(self)
palette.setBrush(QPalette.Background,QBrush(QPixmap("ImageTest.jpg")))
self.setPalette(palette)
No more errors but my background is still blank. Same thing if I just try to fill a color instead of the image.
Unless it's a top-level widget, you need to set the autoFillBackground property to get this to work:
def initBoard(self):
self.setAutoFillBackground(True)
palette = QPalette(self)
palette.setBrush(QPalette.Background, QBrush(QPixmap("ImageTest.jpg")))
self.setPalette(palette)
Alternatively, and more simply, use a style-sheet to set the background image:
def initBoard(self):
self.setStyleSheet('background-image: url("ImageTest.jpg")')

Categories

Resources