How to change the opacity of a PyQt5 window - python

I have just been experimenting with some animation in PyQt5 and am looking to animate the opacity of a window. I have had success with animating the opacity of buttons and QWidgets withink the window, however when I try to apply the same concept to the main QWidget class it doesn't seem to work. Below is my code for trying to get the animation to work on the window (I am aware this isn't the best looking code but I'm just trying to experiment, but also feel free to tell me about any big errors unrelated to the problem as well as I am also quite new to PyQt5):
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
class Test(QWidget):
def __init__(self):
super().__init__()
self.setStyleSheet("background: green")
self.setGeometry(100, 100, 400, 400)
self.b = QPushButton("Reduce", self, clicked=self.reduce)
self.b.show()
self.b.setStyleSheet("color: yellow")
self.show()
def reduce(self):
self.eff = QGraphicsOpacityEffect(self)
self.eff.setOpacity(1)
self.setGraphicsEffect(self.eff)
self.anim = QPropertyAnimation(self.eff, b"opacity")
self.anim.setDuration(500)
self.anim.setStartValue(1)
self.anim.setEndValue(0)
self.anim.start()
self.t = QTimer()
self.t.timeout.connect(self.loop)
self.t.start(10)
print(self.eff.opacity())
def loop(self):
self.update()
print(self.eff.opacity())
if self.anim.currentValue() == 0:
self.t.stop()
self.update()
if __name__ == "__main__":
window = QApplication(sys.argv)
app = Test()
window.exec_()
I thought maybe I am getting odd results as it isn't possible to do this when the widget is made to be the main widget in the window, however I also don't see why that would be a thing. What seems to happen for me is that the window does nothing and nothing changes, other than the button seems to half freeze, as in I am able to click it and get a result (run the function it is connected too) however no pressing down animation occurs as normally would. However, when I resize the window it will show a change, however this has to be manual as I added a basic loop to constantly resize and it did nothing. And finally when I resize the window, or change the opacity just by changing the opacity of self.eff it changes, but it just makes it all black even at values of 0.8, etc which is what leads me to believe it just isn't possible and some script is defaulting it to black, as the button will work fine while the rest goes black. Any help is appreciated.

Try like this:
import sys
from PyQt5.Qt import *
class Test(QWidget):
def __init__(self):
super().__init__()
self.setStyleSheet("background: green;")
self.resize(400, 400)
self.label = QLabel()
self.pixmap = QPixmap('Ok.png')
self.label.setPixmap(self.pixmap)
self.label.setAlignment(Qt.AlignCenter)
self.label.setStyleSheet("background: #CD113B;")
self.b = QPushButton("Reduce", self, clicked=self.reduce)
self.b.setStyleSheet("background: blue; color: yellow;")
layout = QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.b)
def reduce(self):
self.anim = QPropertyAnimation(self, b"opacity")
self.anim.setDuration(3000)
self.anim.setLoopCount(3)
self.anim.setStartValue(0.0)
self.anim.setEndValue(1.0)
self.anim.start()
def windowOpacity(self):
return super().windowOpacity()
def setWindowOpacity(self, opacity):
super().setWindowOpacity(opacity)
opacity = pyqtProperty(float, windowOpacity, setWindowOpacity)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Test()
w.show()
sys.exit(app.exec_())
or so:
import sys
from PyQt5.Qt import *
class Test(QWidget):
def __init__(self):
super().__init__()
self.setStyleSheet("background: green;")
self.resize(400, 400)
self.label = QLabel()
self.pixmap = QPixmap('Ok.png')
self.label.setPixmap(self.pixmap)
self.label.setAlignment(Qt.AlignCenter)
self.label.setStyleSheet("background: #CD113B;")
self.b = QPushButton("Reduce", self, clicked=self.reduce)
self.b.setStyleSheet("background: blue; color: yellow;")
layout = QVBoxLayout(self)
layout.addWidget(self.label)
layout.addWidget(self.b)
def reduce(self):
self.eff = QGraphicsOpacityEffect()
self.eff.setOpacity(1.0)
self.label.setGraphicsEffect(self.eff)
self.anim = QPropertyAnimation(self.eff, b"opacity")
self.anim.setDuration(3000)
self.anim.setLoopCount(3)
self.anim.setStartValue(0.0)
self.anim.setEndValue(1.0)
self.anim.start()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Test()
w.show()
sys.exit(app.exec_())
Ok.png

Related

How to move picbutton? Pyqt5 python

I want to make a button from a picture.
I found this code in here, but i cant move the picture, how can i do that?
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class PicButton(QAbstractButton):
def __init__(self, pixmap, parent=None):
super(PicButton, self).__init__(parent)
self.pixmap = pixmap
def paintEvent(self, event):
painter = QPainter(self)
# painter.drawPixmap(100,1, self.pixmap)
painter.drawPixmap(500,1,100,100, self.pixmap,0,0,100,100)
def sizeHint(self):
return self.pixmap.size()
def close():
print("xxx")
app = QApplication(sys.argv)
window = QWidget()
layout = QHBoxLayout(window)
window.setFixedSize(740, 850) #window size.
button = PicButton(QPixmap("thinking.png"))
button.clicked.connect(close)
layout.addWidget(button)
window.show()
sys.exit(app.exec_())
I can move in x axis but cant in y axis.
How can i do that?
And is there any cursor style to make this more like button?
Thank you.
here is output

How to make a qframe highlight when cursor is on it in PyQt4?

I have the following window with frames.
I want frame to be highlighted (in my case change its shape) when mouse is in its area.
from PyQt4 import QtGui, QtCore
import sys
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window_layout = QtGui.QVBoxLayout()
window.setLayout(window_layout)
#fill content
for i in range(10):
label = QtGui.QLabel(str(i))
frame = QtGui.QFrame()
frame_layout = QtGui.QVBoxLayout()
frame.setLayout(frame_layout)
frame_layout.addWidget(label)
window_layout.addWidget(frame)
def layout_widgets(layout):
return (layout.itemAt(i) for i in range(layout.count()))
def mouse_enter(event):
print 'frame enter'
w.widget().setFrameShape(3)
def mouse_leave(event):
print 'frame leave'
w.widget().setFrameShape(0)
for w in layout_widgets(window_layout):
print w.widget()
w.widget().enterEvent = mouse_enter
w.widget().leaveEvent = mouse_leave
window.show()
sys.exit(app.exec_())
It works but only the last frame in layout highlights.
How to make only that frame change its shape where the mouse is?
I've tried the following:
def mouse_enter(event, frame):
print 'frame enter'
frame.setFrameShape(3)
w.widget().enterEvent = functools.partial(mouse_enter, w.widget())
but it gives an error. I have found one more way to do that - signal mapper
but I have no idea how to use it.
The problem in your code the variable w when executing the for is left with the last element, so it will only be executed in the latter. To solve this I have implemented a Frame class that inherits from QFrame where I overwrite the enterEvent and leaveEvent functions.
from PyQt4 import QtGui, QtCore
import sys
class Frame(QtGui.QFrame):
def __init__(self, text, parent=None):
super(Frame, self).__init__(parent=parent)
label = QtGui.QLabel(text)
frame_layout = QtGui.QVBoxLayout()
frame_layout.addWidget(label)
self.setLayout(frame_layout)
def enterEvent(self, event):
self.setFrameShape(3)
def leaveEvent(self, event):
self.setFrameShape(0)
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window_layout = QtGui.QVBoxLayout()
window.setLayout(window_layout)
for i in range(10):
frame = Frame(str(i))
window_layout.addWidget(frame)
window.show()
sys.exit(app.exec_())

How to deal with layouts in PyQt4?

I want to display welcome label in middle of frame, how can I do that? It seems like layout problem as I googled but I haven't got final solution.
Here is the code:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
palette = QPalette()
palette.setBrush(QPalette.Background, QBrush(QPixmap("Login page.jpg")))
self.setPalette(palette)
self.setWindowTitle("Login Frame")
self.setWindowIcon(QIcon('logo.png'))
self.setGeometry(50, 50, 500, 300)
self.setFixedSize(500, 300)
self.addWidgets()
def addWidgets(self):
self.lblWelcome = QLabel("Welcome to Railway e-Ticketing System", self)
self.lblWelcome.move(100,30)
wcFont = QFont("Open Sans", 25)
self.lblWelcome.setFont(wcFont)
self.lblUid = QLabel("User ID:", self)
self.lblUid.move(100,80)
font = QFont("Open Sans", 10)
self.lneUid = QLineEdit(self)
self.lneUid.setFont(font)
self.lneUid.setFixedHeight(25)
self.lneUid.setFixedWidth(200)
self.lneUid.move(225, 80)
self.lblPass = QLabel("Password:", self)
self.lblPass.move(100, 130)
self.lnePass = QLineEdit(self)
self.lnePass.setEchoMode(QLineEdit.Password)
self.lnePass.setFixedHeight(25)
self.lnePass.setFixedWidth(200)
self.lnePass.move(225, 130)
self.lblInvalid = QLabel("",self)
self.lblInvalid.move(100, 180)
self.btnLogin = QPushButton("Login",self)
#btnLogin.resize(btnLogin.sizeHint())
self.btnLogin.move(175, 230)
self.btnLogin.clicked.connect(self.authenticate)
#self.authenticate()
self.btnReg = QPushButton("Register", self)
self.btnReg.move(300, 230)
#btnReg.clicked.connect(register)
self.show()
def authenticate(self):
uid = self.lneUid.text()
upass = self.lnePass.text()
if(len(uid.strip()) == 0 or len(upass.strip()) == 0):
palette = QPalette()
palette.setColor(QPalette.Foreground, Qt.darkRed)
self.lblInvalid.setPalette(palette)
self.lblInvalid.setText("*Invalid credentials .")
else:
self.lblInvalid.setText("")
def main():
app = QApplication(sys.argv)
LoginWin = Window()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
And here is the output:
You are using a QMainWindow which already has a layout with a central widget, a toolbar, a menu bar etc. The right way to use it is to define a central Widget, and put all your label and buttons in it. You didn't, so your label is not displayed properly.
But for your login frame, you clearly don't need all of this. You just need a QWidget:
import sys
from PyQt4 import QtCore,QtGui
class LoginFrame(QtGui.QWidget):
def __init__(self):
super(LoginFrame, self).__init__()
...
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
win = LoginFrame()
win.show()
sys.exit(app.exec_())
Your code should work with a QWidget, but I would still advise reading about box layout. Right now, you're using absolute positioning, which means you have to manually place your widget at a precise position, and you can't resize your window.
A box layout would be more flexible, and practical. For example you can use QFormLayout for the userID and password.
More about layouts on the ZetCode tutorial

How to resize the main window again after setFixedSize()?

I would like to resize the MainWindow (QMainWindow) after I make some widgets unvisible and vice versa. And I want to block the window resize.
def hideAndShowWidget(self):
self.widgetObject.setVisible(not self.widgetObject.isVisible() )
# change main window size here
# ...
self.setFixedSize(self.width(), self.height())
My problem is, that i can not change the window size after i call setFixedSize() first time. I read here that I must use QWIDGETSIZE_MAX() to remove constraints, but I don't know how can I use it, I get the error:
NameError: name 'QWIDGETSIZE_MAX' is not defined
I think you have the mechanism more or less right. You just have to make sure the height calculation is done correctly (i.e. before the visibility of the widget changes).
The following example works correctly for me (only tested on Linux, though):
from PySide import QtGui
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.widgetObject = QtGui.QTextEdit(self)
self.button = QtGui.QPushButton('Hide Widget', self)
self.button.clicked.connect(self.hideAndShowWidget)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button)
layout.addWidget(self.widgetObject)
self.setFixedSize(300, 200)
def hideAndShowWidget(self):
height = self.height()
if self.widgetObject.isVisible():
height -= self.widgetObject.height()
self.widgetObject.setVisible(False)
self.button.setText('Show Widget')
else:
height += self.widgetObject.height()
self.widgetObject.setVisible(True)
self.button.setText('Hide Widget')
self.setFixedSize(self.width(), height)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
Use the sizeHint(). It contains the size the widget would like to have. Set the fixed size exactly to the size hint.
Working example:
from PySide import QtGui
class Window(QtGui.QMainWindow):
def __init__(self):
super().__init__()
self.setFixedSize(400, 300)
widget = QtGui.QWidget()
layout = QtGui.QVBoxLayout(widget)
button = QtGui.QPushButton('Toggle visibility')
button.clicked.connect(self.hideAndShowWidget)
layout.addWidget(button)
self.widgetObject = QtGui.QLabel('Test')
layout.addWidget(self.widgetObject)
self.setCentralWidget(widget)
def hideAndShowWidget(self):
self.widgetObject.setVisible(not self.widgetObject.isVisible() )
# change main window size
self.setFixedSize(self.sizeHint())
app = QtGui.QApplication([])
w = Window()
w.show()
app.exec_()

Animate using a pixmap or image sequence in Python with QT4

I have a small Python script that makes a transparent window for displaying a graphic on screen and I'd like to animate that graphic, but am entirely unsure how or where to even start. Here's what I do have at least:
import sys
from PyQt4 import QtGui, Qt, QtCore
class Transparent(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.setAttribute(Qt.Qt.WA_NoSystemBackground)
self.setAutoFillBackground(True)
pixmap = QtGui.QPixmap("test1.gif")
pixmap2 = QtGui.QPixmap("test2.gif")
width = pixmap.width()
height = pixmap.height()
self.setWindowTitle("Status")
self.resize(width, height)
self.label = QtGui.QLabel(self)
def animateEvent():
imgnumber = 0
try:
if imgnumber == 1:
self.label.setPixmap(QtGui.QPixmap("test1.gif"))
self.setMask(pixmap.mask())
imgnumber = 0
else:
self.label.setPixmap(QtGui.QPixmap("test2.gif"))
self.setMask(pixmap2.mask())
imgnumber = 1
finally:
QtCore.QTimer.singleShot(1000, animateEvent)
animateEvent()
def paintEvent(self,event):
self.setAttribute(Qt.Qt.WA_NoSystemBackground)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
x = Transparent()
x.show()
app.exec_()
This feels like it has the right ingredients, but the pixmap doesn't update.
I tried QMovie, but then the area of the window that is supposed to be transparent is filled with black instead.
check out this code from www.daniweb.com and see if you can modify it to your needs:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MoviePlayer(QWidget):
def __init__(self, gif, parent=None):
super(MoviePlayer, self).__init__(parent)
self.setGeometry(200, 200, 400, 400)
self.setWindowTitle("QMovie to show animated gif")
self.movie_screen = QLabel()
self.movie_screen.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.movie_screen.setAlignment(Qt.AlignCenter)
btn_start = QPushButton("Start Animation")
btn_start.clicked.connect(self.start)
btn_stop = QPushButton("Stop Animation")
btn_stop.clicked.connect(self.stop)
main_layout = QVBoxLayout()
main_layout.addWidget(self.movie_screen)
main_layout.addWidget(btn_start)
main_layout.addWidget(btn_stop)
self.setLayout(main_layout)
self.movie = QMovie(gif, QByteArray(), self)
self.movie.setCacheMode(QMovie.CacheAll)
self.movie.setSpeed(100)
self.movie_screen.setMovie(self.movie)
def start(self):
"""
Start animation
"""
self.movie.start()
def stop(self):
"""
Stop the animation
"""
self.movie.stop()
app = QApplication(sys.argv)
player = MoviePlayer("/path/to/image.gif")
player.show()
sys.exit(app.exec_())
This ended up being a simple correction of an oversight in the end.
imgnumber needed to be outside of the def as self.imgnumber and needed to be named self.imgnumber each time it was changed.
First, just make sure your animated gif really does have a proper transparent background. The following code works for me, using this fire image as a source:
class Transparent(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.setAttribute(QtCore.Qt.WA_NoSystemBackground)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
filename = "test.gif"
size = QtGui.QImage(filename).size()
self.setWindowTitle("Status")
layout = QtGui.QVBoxLayout(self)
layout.setMargin(0)
self.movie = QtGui.QMovie(filename)
self.label = QtGui.QLabel(self)
self.label.setMovie(self.movie)
layout.addWidget(self.label)
self.resize(size)
self.movie.start()
This will create a completely transparent and frameless window, with the animated gif playing in a QMovie. There is no black being drawn behind the image. It should fully see through to what ever is underneath.
It is not so far off from your original code. You shouldn't need to set the mask, or do a paint event.

Categories

Resources