I am trying to generate a visualizer where each time you press a button the image in a window change. The image have to be in the same window where the button is and it has to replace the previous image.
So for I am able to show the button and the first image. But I cannot connect the click button with the image updating process.
This is my code so far:
author__ = 'lpp'
#!/usr/bin/python
import os,sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('Test', 10))
self.setToolTip('This is a <b>QWidget</b> widget')
# Show image
pic = QtGui.QLabel(self)
pic.setGeometry(10, 10, 800, 800)
pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/Image1.png"))
# Show button
btn = QtGui.QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.clicked.connect(self.fun)
btn.move(50, 50)
self.setGeometry(300, 300, 2000, 1500)
self.setWindowTitle('Tooltips')
self.show()
# Connect button to image updating
def fun(self):
#print("Test!!!")
pic = QtGui.QLabel(self)
pic.setGeometry(100, 10, 800, 800)
pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/image2.png"))
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
All but the "def fun" works.
I also tried these functions but it did not work:
def fun(self):
pic = QtGui.QLabel(self)
pic.setGeometry(100, 10, 800, 800)
pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/image2.png"))
return (pic)
def fun(self):
#print("Test!!!")
pic = QtGui.QLabel(self)
pic.setGeometry(100, 10, 800, 800)
pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/image2.png"))
return self.show()
If you want the previous image you should not create a new QLabel, but just update the QPixmap.
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('Test', 10))
self.setToolTip('This is a <b>QWidget</b> widget')
# Show image
self.pic = QtGui.QLabel(self)
self.pic.setGeometry(10, 10, 800, 800)
self.pic.setPixmap(QtGui.QPixmap("/home/lpp/Desktop/image1.png"))
# Show button
btn = QtGui.QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.clicked.connect(self.fun)
btn.move(50, 50)
self.setGeometry(300, 300, 2000, 1500)
self.setWindowTitle('Tooltips')
self.show()
# Connect button to image updating
def fun(self):
self.pic.setPixmap(QtGui.QPixmap( "/home/lpp/Desktop/image2.png"))
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Related
I want a button that shows a text with two colors. I've tried the following:
import sys
from PyQt4 import QtCore,QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def clicked(self,name):
self.drop_btns_hide(self.dropdown)
print("Clicked on {}".format(name))
def initUI(self):
QtGui.QToolTip.setFont(QtGui.QFont('SansSerif', 10))
self.phslst = ['abc','def','ghi','jkl']
self.setToolTip('This is a <b>QWidget</b> widget')
btn = QtGui.QToolButton(self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.move(50, 50)
text = QtGui.QTextDocument()
text.setHtml('<b>'
'<font color="#0085C8" size="6" face="Avenir">'
'Select Phase'
'</font>'
'<font color="#d8d8d8" size="6">'
'▼'
'</font>'
'</b>')
pixmap = QtGui.QPixmap(text.size().width(), text.size().height())
pixmap.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(pixmap)
text.drawContents(painter, QtCore.QRectF(pixmap.rect()))
icon = QtGui.QIcon(pixmap)
self.select_icon = icon
btn.setIcon(icon)
btn.setIconSize(pixmap.size())
btnA = QtGui.QPushButton('Test', self)
btnA.setToolTip('This is a <b>QPushButton</b> widget')
btnA.resize(btnA.sizeHint())
btnA.move(10, 100)
self.setGeometry(300, 300, 250, 250)
self.setWindowTitle('Tooltips')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
but I'm getting:
QPaintDevice: Cannot destroy paint device that is being painted
fish: “python QToolButton.py” terminated by signal SIGSEGV (Address boundary error)
and I don't understand why.
The QPainter methods are not executed immediately since for efficiency reasons what these methods do is accumulate instructions. And that's what happens in your case since the QPainter is still active and has the property of the QPixmap, that's why you get that error, so in this case the solution is to invoke the end() method:
text = QtGui.QTextDocument()
text.setHtml('<b>'
'<font color="#0085C8" size="6" face="Avenir">'
'Select Phase'
'</font>'
'<font color="#d8d8d8" size="6">'
'▼'
'</font>'
'</b>')
pixmap = QtGui.QPixmap(text.size().toSize())
pixmap.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(pixmap)
text.drawContents(painter, QtCore.QRectF(pixmap.rect()))
painter.end() # <-- this line
icon = QtGui.QIcon(pixmap)
btn.setIcon(icon)
btn.setIconSize(pixmap.size())
I'm trying to make a player for a custom file in PyQT5 and I have a set of images that I want to render in a PyQt widget one after another so I can play it as a continious video. So my question is how can I do something like that? Some code example or a guide would be great. Thank you.
EDIT:
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.scene = QGraphicsScene()
self.pixmap = QGraphicsPixmapItem()
self.scene.addItem(self.pixmap)
self.initUI().graphicsView.setScene(self.scene)
self.initUI()
def initUI(self):
graphicsView = QGraphicsView()
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Test')
self.show()
In your widget, you can add a QGraphicsVew, add a QGraphicsScene to the graphicsview, add a pixmap to the scene and continuously change the pixmap through setPixmap() function.
So in the constructor of your widget, add these (it is assumed that your .ui file has a QGraphicsView called graphicsView):
self.scene = QtWidgets.QGraphicsScene()
self.pixmap = QtWidgets.QGraphicsPixmapItem()
self.scene.addItem(self.pixmap)
self.ui.graphicsView.setScene(self.scene)
In your player function, which is called periodically, you set the pixmap:
self.t1_pixmap.setPixmap(img)
where img contains the pixmap loaded from your image files.
Update (based on the code given, and a correction):
import sys
from PyQt5 import QtWidgets, QtGui
class Example(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.initUI()
def initUI(self):
graphicsView = QtWidgets.QGraphicsView(self)
scene = QtWidgets.QGraphicsScene()
self.pixmap = QtWidgets.QGraphicsPixmapItem()
scene.addItem(self.pixmap)
graphicsView.setScene(scene)
self.setGeometry(300, 300, 300, 200)
graphicsView.resize(300,200)
self.setWindowTitle('Test')
self.show()
def play(self):
img = QtGui.QPixmap('D:\\tmp\\image.png')
self.pixmap.setPixmap(img)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = Example()
window.play()
app.exec()
sys.exit()
I want to emit a signal from a QGraphicsItem when it is doubled-clicked, in order to change a widget in the main window. The graphics-scene/-item does not provide an emit() method, but I was just wondering if there is an alternate way to do this. The code below has a function within a QGraphicsView class that will print to the terminal when an item is double-clicked. How can I make that into a slot/signal instead (if QGraphicsItem does not support signal/slots)?
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class MyFrame(QGraphicsView):
def __init__( self, parent = None ):
super(MyFrame, self).__init__(parent)
scene = QGraphicsScene()
self.setScene(scene)
self.setFixedSize(500, 500)
pen = QPen(QColor(Qt.green))
brush = QBrush(pen.color().darker(150))
item = scene.addEllipse(0, 0, 45, 45, pen, brush)
item.setPos(0,0)
def mouseDoubleClickEvent(self, event):
print("Circle Clicked!")
# this double click event prints to terminal but how to setup
# signal/slot to update the QWidget QLabel text instead?
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QHBoxLayout(self)
top = QLabel("Double Click Green Circle (Howto change this QWidget Label with signals?)")
bottom = MyFrame()
splitter = QSplitter(Qt.Vertical)
splitter.addWidget(top)
splitter.addWidget(bottom)
hbox.addWidget(splitter)
self.setLayout(hbox)
self.setGeometry(0, 0, 500, 600)
self.show()
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Below is a simple example showing one way to emit signals from a graphics-item. This defines a custom signal on a subclass of QGraphicsScene and then uses the scene() method of graphics-items to emit it:
import sys
from PySide import QtCore, QtGui
class GraphicsScene(QtGui.QGraphicsScene):
itemDoubleClicked = QtCore.Signal(object)
class GraphicsRectangle(QtGui.QGraphicsRectItem):
def mouseDoubleClickEvent(self, event):
self.scene().itemDoubleClicked.emit(self)
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.view = QtGui.QGraphicsView()
self.scene = GraphicsScene(self)
self.view.setScene(self.scene)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.view)
for i in range(1, 4):
self.scene.addItem(GraphicsRectangle(50 * i, 50 * i, 20, 20))
self.scene.itemDoubleClicked.connect(self.handleItemDoubleClicked)
def handleItemDoubleClicked(self, item):
print(item.boundingRect())
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.setGeometry(600, 100, 300, 200)
window.show()
sys.exit(app.exec_())
UPDATE:
Below is a an example based on the code in your question. The basic idea is the same: define a custom signal on an available QObject (the graphics-view in this case), and use that to emit the double-click notification.
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class MyFrame(QGraphicsView):
itemDoubleClicked = Signal(object)
def __init__(self, parent=None):
super(MyFrame, self).__init__(parent)
scene = QGraphicsScene()
self.setScene(scene)
self.setFixedSize(500, 500)
for i, color in enumerate('red blue green'.split()):
pen = QPen(QColor(color))
brush = QBrush(pen.color().darker(150))
item = scene.addEllipse(i * 50, i * 50, 45, 45, pen, brush)
item.setData(0, color.upper())
def mouseDoubleClickEvent(self, event):
item = self.itemAt(event.pos())
if item is not None:
self.itemDoubleClicked.emit(item)
class Example(QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QHBoxLayout(self)
top = QLabel('Double Click a Circle')
bottom = MyFrame()
bottom.itemDoubleClicked.connect(
lambda item, top=top:
top.setText('Double Clicked: %s' % item.data(0)))
splitter = QSplitter(Qt.Vertical)
splitter.addWidget(top)
splitter.addWidget(bottom)
hbox.addWidget(splitter)
self.setLayout(hbox)
self.setGeometry(0, 0, 500, 600)
self.show()
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
My Probleme is i want to add to a label respectively text a event in my case the mousePressEvent.But it dont work under this text is some code from me that doesn´t work.
self.label2.mousePressEvent = self.credits
def credits(self, event):
print("credits")
Here i get the error AttributeError: 'Window' object has no attribute 'label2'
I also try this one:
label2.mousePressEvent.connect(self.credits)
def credits(self):
print("credits")
That doenst work too :( Any Ideas i am glad if anybody can help me :(
if you need the full code here:
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 Window(QWidget):
def __init__(self):
super().__init__()
self.initMe()
def initMe(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)
self.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)
self.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)
self.label4.mousePressEvent = self.credits
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;")
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")
def settings(self, event):
print("settings")
def credits(self, event):
print("credits")
def gedruekt(self):
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")
The problem is that the variables are not members of the classes so it is not necessary to use the self instance, for this it changes for example:
self.label2.mousePressEvent = self.spielen
to:
label2.mousePressEvent = self.spielen
If you want to use connect, this is only for signals, for this we create a custom QLabel class like the following:
class Label(QLabel):
clicked = pyqtSignal()
def __init__(self, parent=None):
QLabel.__init__(self, parent=parent)
def mousePressEvent(self, event):
self.clicked.emit()
In this case you will be as follows:
class Label(QLabel):
clicked = pyqtSignal()
def __init__(self, parent=None):
QLabel.__init__(self, parent=parent)
def mousePressEvent(self, event):
self.clicked.emit()
class Window(QWidget):
def __init__(self):
super().__init__()
self.initMe()
def initMe(self):
label1 = 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 = Label(self)
label2.setText("Spielen")
label2.setStyleSheet("font-size: 18px;color: black;")
label2.setGeometry(50, 50, 400, 100)
label2.move(450, 120)
label2.clicked.connect(self.spielen)
label3 = Label(self)
label3.setText("Settings")
label3.setStyleSheet("font-size: 18px;color: black;")
label3.setGeometry(50, 50, 400, 100)
label3.move(450, 200)
label3.clicked.connect(self.settings)
label4 = Label(self)
label4.setText("Credits")
label4.setStyleSheet("font-size: 18px;color: black;")
label4.setGeometry(50, 50, 400, 100)
label4.move(450, 280)
label4.clicked.connect(self.credits)
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(self.close)
button.clicked.connect(self.gedruekt)
button.setStyleSheet("background-color: white;")
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):
print("spielen")
def settings(self):
print("settings")
def credits(self):
print("credits")
def gedruekt(self):
print("Er hats getan ;(")
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Window()
sys.exit(app.exec_())
I am new to PyQT5 and I want to have several buttons and have the one clicked last in a "checked" state. When another button is clicked the previous one gets "unchecked" while the clicked one gets "checked".
import sys
from PyQt5.QtWidgets import *
class Example(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(30, 30, 400, 200)
self.initUI()
def initUI(self):
self.button1 = QPushButton(self)
self.button1.setGeometry(40, 40, 100, 50)
self.button1.setText("Button 1")
self.button2 = QPushButton(self)
self.button2.setGeometry(150, 40, 100, 50)
self.button2.setText("Button 2")
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Building off of your code, you can add button1 and button2 to a QButtonGroup with the exclusive property set to True.
class Example(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(30, 30, 400, 200)
self.initUI()
def initUI(self):
self.button1 = QPushButton(self)
self.button1.setGeometry(40, 40, 100, 50)
self.button1.setText("Button 1")
self.button2 = QPushButton(self)
self.button2.setGeometry(150, 40, 100, 50)
self.button2.setText("Button 2")
self.btn_grp = QButtonGroup()
self.btn_grp.setExclusive(True)
self.btn_grp.addButton(self.button1)
self.btn_grp.addButton(self.button2)
self.btn_grp.buttonClicked.connect(self.on_click)
self.show()
def on_click(self, btn):
pass # do something with the button clicked
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Here I've also connected an empty slot to the signal QButtonGroup.buttonClicked, which is emitted whenever a button from the group is clicked.
To find out which button is the currently checked button, you can invoke the methods QButtonGroup.checkedButton() and QButtonGroup.checkedId(). The former will return a QButton object and the latter will return an index int, corresponding to the order in which the buttons were added to the group.
You can use functools partial or the sender method to check which button was pressed:
import sys
from PyQt5.QtWidgets import *
from functools import partial
class Example(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(30, 30, 400, 200)
self.initUI()
def initUI(self):
self.button1 = QPushButton(self)
self.button1.setGeometry(40, 40, 100, 50)
self.button1.setText("Button 1")
self.button1.clicked.connect(partial(self.clicked_btn, 'Button 1'))
self.button2 = QPushButton(self)
self.button2.setGeometry(150, 40, 100, 50)
self.button2.setText("Button 2")
self.button2.clicked.connect(partial(self.clicked_btn, 'Button 2'))
self.show()
def clicked_btn(self, value):
print(f'{value} clicked')
sender = self.sender()
print(f'Sender says: {sender.text()} was clicked')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
Make the buttons checkable by setCheckable(True)
Add the buttons to a QButtonGroup() and the rest is sorted automatically:
class Example(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(30, 30, 400, 200)
self.initUI()
def initUI(self):
self.button1 = QPushButton(self)
self.button1.setGeometry(40, 40, 100, 50)
self.button1.setText("Button 1")
self.button1.setCheckable(True)
self.button2 = QPushButton(self)
self.button2.setGeometry(150, 40, 100, 50)
self.button2.setText("Button 2")
self.button2.setCheckable(True)
self.my_button_group = QButtonGroup()
self.my_button_group.addButton(self.button1)
self.my_button_group.addButton(self.button2)
self.show()