This question already has answers here:
Is there a way to implement a circular waiting indicator using PyQt?
(2 answers)
Spinning animation while another process is running in pyqt
(1 answer)
Closed 3 days ago.
i need to do make a loading circle in my program using PyQt5
what is the loading circle that i mean? this is it :
it is a circle spins to tells you this thing is loading or something like that , you can see it when you run a video on youtube.
whet i have done :
i wrote a code that is doing what i want , but i have a problem my problem is this code sometimes is crashing or stopping the spinning operation.
for that i ask for some idea better that my idea
this is my code :
import sys
from PyQt5 import QtWidgets,QtCore,QtGui
import threading
import time
app = QtWidgets.QApplication(sys.argv)
windows = QtWidgets.QWidget()
window_layout = QtWidgets.QGridLayout()
def to_run():
while True:
donwloading_label.setStyleSheet("""
background-color:rgba(0,0,0,0);
border-radius:250;
border-style:solid;
border-color:rgba(0, 0, 0,0);
border-width:25;
color:rgb(255,255,255);
font-size:30px;
border-top-color:rgb(0, 0, 0);
""")
time.sleep(0.1)
donwloading_label.setStyleSheet("""
background-color:rgba(0,0,0,0);
border-radius:250;
border-style:solid;
border-color:rgba(0, 0, 0,0);
border-width:25;
color:rgb(255,255,255);
font-size:30px;
border-right-color:rgb(0, 0, 0);
""")
time.sleep(0.1)
donwloading_label.setStyleSheet("""
background-color:rgba(0,0,0,0);
border-radius:250;
border-style:solid;
border-color:rgba(0, 0, 0,0);
border-width:25;
color:rgb(255,255,255);
font-size:30px;
border-bottom-color:rgb(0, 0, 0);
""")
time.sleep(0.1)
donwloading_label.setStyleSheet("""
background-color:rgba(0,0,0,0);
border-radius:250;
border-style:solid;
border-color:rgba(0, 0, 0,0);
border-width:25;
color:rgb(255,255,255);
font-size:30px;
border-left-color:rgb(0, 0, 0);
""")
time.sleep(0.1)
def any():
tt = threading.Thread(target=to_run)
tt.start()
donwloading_label = QtWidgets.QLabel()
donwloading_label.setAlignment(QtCore.Qt.AlignCenter)
donwloading_label.setText("Please Wait....")
donwloading_label.setFixedSize(500,500)
donwloading_label.setStyleSheet("""
background-color:rgba(0,0,0,0);
border-radius:250;
border-style:solid;
border-color:rgba(0, 0, 0,0);
border-width:25;
color:rgb(255,255,255);
font-size:30px;
""")
any()
window_layout.addWidget(donwloading_label)
windows.setLayout(window_layout)
windows.show()
sys.exit(app.exec_())
Related
I have a simple Python application with a PyQt QTableWidget with multiple columns and rows. If the user resizes a column to a size that is just smaller than the cell can hold.. the font of the cell will shrink by about 1 point in size (see animated GIF below). I have fiddled with almost every QTableWidget setting in QtDesigner. I would like the font size to remain consistent regardless.
What is causing this and how can I prevent it?
Update:
In my __main__ section, I create a stylesheet for buttons.
I apply this style sheet using setStyleSheet.
If I comment-out setStyleSheet, the problem goes away.
Adding QTableWidget{font: 9pt "Segoe UI";} also fixes, but I'd rather not do that.
Why is this stylesheet causing this?
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
stylesheet = """
QPushButton:hover, QComboBox:hover
{
background-color: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #cbc9c5, stop: 1 #b9b7b5);
border: 2px solid #78879b;
border-radius: 3px;
}
"""
app.setStyleSheet(stylesheet)
myapp = MyProgram() # instantiate the main window
myapp.show() # show the main window
rc = app.exec_()
myapp.close()
sys.exit(rc) # exit with the same return code of Qt application
I'm currently trying to fade a specific QLabel in and out. My first try was to use the setAlphaChannel, however this just didn't work.
My current approach is to use a for-loop and set the stylesheet of the QLabel. Sadly this makes a unverifiable bug, sometimes the fading works properly, sometimes the QLabel doesn't fade out but is fading in and more random stuff. For me the problem is untraceable.
Here is my current code:
def fade_greeting(self, foo, bar):
for i in range(255, -1, -5):
print(i)
string = "font : 45px; font : bold; color : rgba(220, 220, 220, " + str (i) + "); font-family : HelveticaNeue-UltraLight"
time.sleep(0.2)
self.greeting_text.setStyleSheet(string)
time.sleep(2)
self.greeting_text.setText(greeting())
time.sleep(2)
for i in range(0, 256, 5):
print(i)
string = "font : 45px; font : bold; color : rgba(220, 220, 220, " + str (i) + "); font-family : HelveticaNeue-UltraLight"
time.sleep(0.2)
self.greeting_text.setStyleSheet(string)
Is there something I missed? Or is there maybe a different approach to this problem?
Already thanks for your help!
After some trial and error, I found a working recipe:
def fade(self, widget):
self.effect = QGraphicsOpacityEffect()
widget.setGraphicsEffect(self.effect)
self.animation = QtCore.QPropertyAnimation(self.effect, b"opacity")
self.animation.setDuration(1000)
self.animation.setStartValue(1)
self.animation.setEndValue(0)
self.animation.start()
def unfade(self, widget):
self.effect = QGraphicsOpacityEffect()
widget.setGraphicsEffect(self.effect)
self.animation = QtCore.QPropertyAnimation(self.effect, b"opacity")
self.animation.setDuration(1000)
self.animation.setStartValue(0)
self.animation.setEndValue(1)
self.animation.start()
I guess you can call it on any widget. I call it on QLabel. For example:
self.fade(self._your_widget_here_)
# or
self.unfade(self._your_widget_here_)
It will fadein or fadeout your widget.
sleep() is a blocking function that is not suitable to use in the main GUI thread, Qt provides tools to handle this type of tasks as QVariantAnimation, it provides the colors in an appropriate way for the required animation.
To change the colors you can use QPalette as I show below:
class AnimationLabel(QLabel):
def __init__(self, *args, **kwargs):
QLabel.__init__(self, *args, **kwargs)
self.animation = QVariantAnimation()
self.animation.valueChanged.connect(self.changeColor)
#pyqtSlot(QVariant)
def changeColor(self, color):
palette = self.palette()
palette.setColor(QPalette.WindowText, color)
self.setPalette(palette)
def startFadeIn(self):
self.animation.stop()
self.animation.setStartValue(QColor(0, 0, 0, 0))
self.animation.setEndValue(QColor(0, 0, 0, 255))
self.animation.setDuration(2000)
self.animation.setEasingCurve(QEasingCurve.InBack)
self.animation.start()
def startFadeOut(self):
self.animation.stop()
self.animation.setStartValue(QColor(0, 0, 0, 255))
self.animation.setEndValue(QColor(0, 0, 0, 0))
self.animation.setDuration(2000)
self.animation.setEasingCurve(QEasingCurve.OutBack)
self.animation.start()
def startAnimation(self):
self.startFadeIn()
loop = QEventLoop()
self.animation.finished.connect(loop.quit)
loop.exec_()
QTimer.singleShot(2000, self.startFadeOut)
class Widget(QWidget):
def __init__(self):
super().__init__()
lay = QVBoxLayout(self)
self.greeting_text = AnimationLabel("greeting_text")
self.greeting_text.setStyleSheet("font : 45px; font : bold; font-family : HelveticaNeue-UltraLight")
lay.addWidget(self.greeting_text)
btnFadeIn = QPushButton("fade in")
btnFadeOut = QPushButton("fade out")
btnAnimation = QPushButton("animation")
lay.addWidget(btnFadeIn)
lay.addWidget(btnFadeOut)
lay.addWidget(btnAnimation)
btnFadeIn.clicked.connect(self.greeting_text.startFadeIn)
btnFadeOut.clicked.connect(self.greeting_text.startFadeOut)
btnAnimation.clicked.connect(self.greeting_text.startAnimation)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Widget()
ex.show()
sys.exit(app.exec_())
given that, I'm starting with the PyQt5 module, I'm still slowly understanding the logic behind it. That said, I'm having a problem that I can not find an answer to and I hope you can help me.
I have this script:
import sys, socket, time
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from io import BytesIO as by
class loadGame(QWidget):
wLoadDisplay = 768
hLoadDisplay = 576
wLoadBar = 650
hLoadBar = 40
pbarCSS = """
QProgressBar
{
font-size: 20px;
font-weight: bold;
background-color: #FFF;
border: 4px solid #000;
text-align: center;
}
QProgressBar::chunk
{
background-color: #FF0000;
width: 1px;
}
"""
labelCSS = """
QLabel
{
font-size: 20px;
font-weight: bold;
background-color: #FFF;
border: 4px solid #000;
}
"""
fileResource = []
imgResource = []
vidResource = []
audResource = []
diaResource = []
txtResource = []
internetConnection = False
def __init__(self, *args, **kwargs):
QWidget.__init__(self, *args, **kwargs)
self.outputFile = by()
self.pbar = QProgressBar(self)
self.pbar.setGeometry((self.wLoadDisplay / 2 - self.wLoadBar / 2), (self.hLoadDisplay / 2 - self.hLoadBar * 2),
self.wLoadBar, self.hLoadBar)
self.pbar.setFormat("%v/%m")
self.pbar.setValue(0)
self.pbar.setStyleSheet(self.pbarCSS)
self.label = QLabel(self)
self.label.setGeometry((self.wLoadDisplay / 2 - self.wLoadBar / 2), (self.hLoadDisplay / 2),
self.wLoadBar, self.hLoadBar)
self.label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
self.label.setStyleSheet(self.labelCSS)
self.setGeometry(0, 0, self.wLoadDisplay, self.hLoadDisplay)
oImage = QImage("bgloading.png")
sImage = oImage.scaled(QSize(self.wLoadDisplay, self.hLoadDisplay))
palette = QPalette()
palette.setBrush(10, QBrush(sImage))
self.setPalette(palette)
qtRectangle = self.frameGeometry()
centerPoint = QDesktopWidget().availableGeometry().center()
qtRectangle.moveCenter(centerPoint)
self.move(qtRectangle.topLeft())
self.run()
def run(self):
self.checkConnection()
if self.internetConnection:
self.checkUpdate()
else:
pass
def checkConnection(self):
self.objectChange("Check Internet Connection", 1)
try:
host = socket.gethostbyname("www.google.it")
s = socket.create_connection((host, 80), 2)
self.internetConnection = True
except:
pass
self.count()
self.reset()
def checkUpdate(self):
pass
def objectChange(self, object, n):
self.label.setText(object)
self.pbar.setMaximum(n)
def count(self):
self.pbar.setValue(self.pbar.value() + 1)
def reset(self):
time.sleep(2)
self.pbar.setMaximum(0)
self.pbar.setValue(0)
self.label.setText("...")
if __name__ == '__main__':
loadDisplay = QApplication(sys.argv)
load = loadGame()
load.show()
sys.exit(loadDisplay.exec_())
Searching on the web, I discovered that the problem is related to "time.sleep (2)", that is, the instruction blocks the window that does not appear until two seconds have passed.
The fact is that I would like to spend one or two seconds, showing the completion of the bar, before resetting and move on to the next statement contained in "def run (self)".
So, is there a way to make that pause, without using the Time module? I do not know, maybe with QTimer? I repeat, I do not know much about PyQt5 yet, so I'm not aware if QTimer can do the same thing.
If QTimer can not do it, is it possible in any other way? I would like to avoid the "threads" of PyQt5, because I read that it would be possible to do it, but I would like to avoid using it only for the Timer module.
I only add one more question, to avoid opening another one and publishing the same script.
In the script, the window background is done via "oImage = QImage (" bgloading.png ")" etc.
I noticed, however, that if the file name were found to be wrong, or the file itself is missing, the background is colored black. So, if there are any errors (wrong name or missing file) it's possible set a background, for example, white?
Because when the window is loaded with "this error", no exception is raised and the script continues.
Edit: I've edited the published script so that it contains only the PyQt5 part, so you can try it out. Obviously only the image is missing, which can be replaced with any image.
Unfortunately I had forgotten to write that the part where "self.set_display ()" was reported was to show that once the work performed by PyQt5 was terminated, it would be closed (which was still missing, because using Pycharm I would close the execution of the script from the program). The script would continue by calling the "self.set_display ()" function.
Edit2: I tried, as suggested, to replace "time.sleep (2)", but I get the same result. The problem is that if I do not put the pause, the window appears normally, but the reset happens too quickly and the user does not see the filling of the progress bar. If instead I put "time.sleep (2)" or, the suggested solution, the window appears only after the pause, that is when the reset has already occurred.
An expression equivalent to time.sleep(2) that is friendly to PyQt is as follows:
loop = QEventLoop()
QTimer.singleShot(2000, loop.quit)
loop.exec_()
The problem is caused because you are showing the widget after the pause, you must do it before calling run(), Also another error is to use QImage, for questions of widgets you must use QPixmap.
If the file does not exist then QPixmap will be null and to know if it is you should use the isNull() method:
[...]
self.setGeometry(0, 0, self.wLoadDisplay, self.hLoadDisplay)
palette = self.palette()
pixmap = QPixmap("bgloading.png")
if not pixmap.isNull():
pixmap = pixmap.scaled(QSize(self.wLoadDisplay, self.hLoadDisplay))
palette.setBrush(QPalette.Window, QBrush(pixmap))
else:
palette.setBrush(QPalette.Window, QBrush(Qt.white))
self.setPalette(palette)
qtRectangle = self.frameGeometry()
centerPoint = QDesktopWidget().availableGeometry().center()
qtRectangle.moveCenter(centerPoint)
self.move(qtRectangle.topLeft())
self.show()
self.run()
[...]
def reset(self):
loop = QEventLoop()
QTimer.singleShot(2000, loop.quit)
loop.exec_()
self.pbar.setMaximum(0)
self.pbar.setValue(0)
self.label.setText("...")
I have a basic OpenGL square drawing code that I want to put another thread using Python. This is the normal code which is working well,
from OpenGL.GLUT import *
from OpenGL.GL import *
from OpenGL.GLU import *
class Drawer:
def drawQuad(self, x,y,width):
halfW=width/2
glBegin(GL_QUADS)
glVertex3f(x-halfW, y-halfW, 0)
glVertex3f(x-halfW, y+halfW, 0)
glVertex3f(x+halfW, y+halfW, 0)
glVertex3f(x+halfW, y-halfW, 0)
glEnd()
def display(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glColor3f(0, 0, 1)
self.drawQuad(0.0,0.0,0.6)
glutSwapBuffers( )
class Visualizer:
drawer = Drawer()
def __init__(self):
glutInit(sys.argv)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)
glutInitWindowSize(250, 250)
glutInitWindowPosition(100, 100)
glutCreateWindow(sys.argv[0])
glutDisplayFunc( self.drawer.display )
glClearColor ( 0, 0, 0, 0 )
glShadeModel( GL_SMOOTH )
glutMainLoop()
visualizer = Visualizer()
This works on my machine flawlessly. Now, I want to put this on a thread. I did the following,
class Thread(threading.Thread):
visualizer = None
def run(self):
self.visualizer = Visualizer()
thread = Thread()
thread.start()
When I run the thread, instead of visualizer itself, it does not work. The OpenGL window does not appear. I cannot see what the problem is.
I tried the threading with some other examples, they seemed working well. I am confused a bit. What is the problem with my threading approach for OpenGL?
I'm baffled by this one. I tried moving the QPainter to it's own def as some have suggested, but it gives the exact same error. Here's the def I created.
def PaintButtons(self):
solid = QtGui.QPixmap(200, 32)
paint = QtGui.QPainter()
paint.begin(solid)
paint.setPen(QtGui.Qcolor(255,255,255))
paint.setBrush(QtGui.QColor(255, 0, 0))
paint.drawRect(0, 0, 200, 32)
paint.end()
It was just a typo. You're using Qcolor (the first occurrence).Changing that to QColor will do the trick. :)