How to run one function only after another, at pushbutton using PYQT - python

I've read multiple posts on this and couldn't fix my code.
I'm running a GUI (using PyQt5) that runs a function (Extraction()) from another script (file_py). What I want to do is the script to display a Green Led picture (.png) at start, and then when pushbutton is clicked, before running Extraction(), the GUI would display a Red Led picture.
from PyQt5 import QtCore, QtGui, QtWidgets
import file_py as my_script
def setupUi(self, MainWindow):
self.pushButton.clicked.connect(self.trigger_status_icon)
self.LED_Green = QtGui.QPixmap("C:/Desktop/green-led-on.png")
self.LED_Red = QtGui.QPixmap("C:/Desktop/red-led-on.png")
self.labelStatus = QtWidgets.QLabel()
self.labelStatus.setPixmap(self.LED_Green) #starting GUI with a Green Led picture
self.labelStatus.setScaledContents(True)
def trigger_status_icon(self):
self.labelStatus.setPixmap(self.LED_Red)
return self.run_Script()
def run_Script(self):
my_script.Extraction()
But what I'm getting with this code is the following: At the start of the GUI a Green Led picture is displayed. After pushbutton is clicked the function Extraction() runs, and only after it finishes the Led Red picture appears.
What can I do so that the Led Red picture is run before the function Extraction()?

By adding QtWidgets.QApplication.processEvents() after assigning the picture it will refresh the QtWidget.
def trigger_status_icon(self):
self.labelStatus.setPixmap(self.LED_Red)
QtWidgets.QApplication.processEvents()
return self.run_Script()

When you have a change in UI followed by some "lengthy" operation you can explicitly refresh the UI by using the QWidget.update method:
def trigger_status_icon(self):
self.labelStatus.setPixmap(self.LED_Red)
self.update()
return self.run_Script()

Related

UI made in QT Designer shifts behind Title Bar [duplicate]

I'm trying to create an application that contains a web browser within it, but when I add the web browser my menu bar visually disappears but functionally remains in place. The following are two images, one showing the "self.centralWidget(self.web_widget)" commented out, and the other allows that line to run. If you run the example code, you will also see that while visually the entire web page appears as if the menu bar wasn't present, you have to click slightly below each entry field and button in order to activate it, behaving as if the menu bar was in fact present.
Web Widget Commented Out
Web Widget Active
Example Code
import os
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtWebEngineWidgets import *
class WebPage(QWebEngineView):
def __init__(self, parent=None):
QWebEngineView.__init__(self)
self.current_url = ''
self.load(QUrl("https://facebook.com"))
self.loadFinished.connect(self._on_load_finished)
def _on_load_finished(self):
print("Url Loaded")
class MainWindow(QMainWindow):
def __init__(self, parent=None):
# Initialize the Main Window
super(MainWindow, self).__init__(parent)
self.create_menu()
self.add_web_widet()
self.show()
def create_menu(self):
''' Creates the Main Menu '''
self.main_menu = self.menuBar()
self.main_menu_actions = {}
self.file_menu = self.main_menu.addMenu("Example File Menu")
self.file_menu.addAction(QAction("Testing Testing", self))
def add_web_widet(self):
self.web_widget = WebPage(self)
self.setCentralWidget(self.web_widget)
if __name__ == "__main__":
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.showMaximized()
sys.exit(app.exec_()) # only need one app, one running event loop
Development Environment
Windows 10, PyQt5, pyqt5-5.9
EDIT
The problem doesn't seem to be directly related to the menu bar. Even removing the menu bar the issue still occurs. That said, changing from showMaximized() to showFullScreen() does seem to solve the problem.
I no longer believe this is an issue with PyQt5 specifically but rather a problem with the graphics driver. Specifically, if you look at Atlassian's HipChat application it has a similar problem which is documented here:
https://jira.atlassian.com/browse/HCPUB-3177
Some individuals were able to solve the problem by running the application from the command prompt with the addendum "--disable-gpu" but that didn't work for my python application. On the other hand, rolling back the Intel(R) HD Graphics Driver did solve my problem. Version 21.20.16.4627 is the one that seems to be causing problems.

Display an image when pressing a button in Qt GUI (Python)

I drew a GUI in Qt Creator, with a button, a slider and some labels.
What I am trying: when the button is pressed, print on terminal and in a label the modified value of the slider and display an image. As many webpages suggested, I am trying to display an image into a label by using the pixmap method. This is my whole code (the structure of the GUI is in the imported mainwindow.ui file)
import sys
from PyQt4 import QtCore, QtGui, uic
qtCreatorFile = "mainwindow.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class myownGUI(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
#button
self.Do_button.clicked.connect(self.action)
#slider
self.SLIDER.valueChanged[int].connect(self.SLIDER_update)
#"global" variable init. by callback
self.SLIDER_update()
#The button callback
def action(self):
print "DOING ACTION!"
print self.Slider
#trying to display the image in the Image_label
image = QtGui.QImage(QtGui.QImageReader(":/images/test.png").read())
self.Image_label.setPixmap(QtGui.QPixmap(image))
#self.Image_label.show() #unuseful command?
#Slider update callback
def SLIDER_update(self):
self.Slider= self.SLIDER.value()
if (self.Slider % 2 == 0): #even
self.Slider = self.Slider + 1
self.Slider_label.setText(str(self.Slider))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = myownGUI()
window.show()
sys.exit(app.exec_())
The code runs, it shows no error but the image is not displayed.
I tried both JPG and PNG images. I tried also the simple image name, when the image is in the same folder.
What is wrong in my code?
There is another way to display images in QT inside the GUI (with python) ?
Thank you in advance
Working with: Ubuntu 14.04 / Qt version 4.8.6
I try to read all similar questions in stack overflow. It seems that my question is duplicated, but none of the answers seems to resolve my problem.
EDIT: Using PRMoureu's syntax it works also when the image is the same folder, like
image = QtGui.QImage(QtGui.QImageReader("./test.png").read())
Now the image is displayed and have only to be rescaled.
You should call the image with another path syntax :
image = QtGui.QImage(QtGui.QImageReader("./images/test.png").read())
or
image = QtGui.QImage(QtGui.QImageReader("images/test.png").read())

PyQt4: Only the last signal is being processed

I ran into a strange problem when working on my project. I have a GUI and a QTextEdit that serves as a status browser. When a button is clicked, I want the QTextEdit to display a 10 second countdown while another function is happening in a separate thread. Even though I emit a signal every second, the QTextEdit hangs for 9 seconds, then displays the last countdown number.
I thought this might have something to do with stuff happening in a separate thread, so I created a separate example to test this out. In my simple example, there are two things: a QTextEdit and a Button. When the button is clicked, the status browser should display '5' for two seconds, then '4'.
Here is the code:
import sys
from PyQt4 import QtGui, uic
from PyQt4.QtCore import QObject, pyqtSignal
import time
class MainUI(QObject):
status_signal = pyqtSignal(str)
def __init__(self, window):
super(QObject, self).__init__()
self.ui = uic.loadUi(r'L:\internal\684.07\Mass_Project\Software\PythonProjects\measure\testing\status_test.ui', window)
self.ui.statusBrowser.setReadOnly(True)
self.ui.statusBrowser.setFontPointSize(20)
self.status_signal.connect(self.status_slot)
self.ui.button.clicked.connect(self.counter)
window.show()
def status_slot(self, message):
self.ui.statusBrowser.clear()
self.ui.statusBrowser.append(message)
def counter(self):
print 'clicked'
i = 5
self.status_signal.emit(str(i))
time.sleep(2)
self.status_signal.emit(str(i-1))
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
app.setStyle("cleanlooks")
main_window = QtGui.QDialog()
main_ui = MainUI(main_window)
sys.exit(app.exec_())
In this example, the same thing happens. The status browser hangs for 2 seconds, then only displays '4'. When I alter the status_slot function so that it doesn't clear the status browser before appending to it, the status browser waits for 2 seconds, then emits both signals at once, displaying '5 \n 4'. Does anyone know why this is happening and what I can do to constantly update the display? Thanks in advance!
time.sleep() blocks the Qt main loop so it can't process window redraw events. Use a QTimer to periodically call a method which emits your signal so that control is returned to the Qt event loop regularly.

Deactivate all buttons during execution - PyQt

I'm building a GUI with PyQt, and I'd like to make it possible to stop all the buttons doing anything while code is running. Lets say the user is copying a lot of data from a table - it would be easy for them to click another button while it is happening even if the cursor has changed to the egg timer. Any ideas or workarounds for this without going through all buttons and greying them out one by one? I'd be happy with a workaround too!
Thanks for any ideas,
Pete
You could use a modal QDialog. From the QDialog pyqt documentation:
A modal dialog is a dialog that blocks input
to other visible windows in the same application.
Also, QProgressDialog is a very convenient tool to handle blocking action in a very simple way. Here is an example :
from PyQt4 import QtGui, QtCore
from time import sleep
class Test(QtGui.QDialog):
def __init__(self, parent=None):
super(Test, self).__init__(parent)
button = QtGui.QPushButton("Button")
hbox = QtGui.QHBoxLayout()
hbox.addWidget(button)
self.setLayout(hbox)
button.clicked.connect(self.slot)
def slot(self):
progress = QtGui.QProgressDialog(self)
progress.setWindowModality(QtCore.Qt.WindowModal)
progress.setLabel(QtGui.QLabel("Doing things..."))
progress.setAutoClose(True)
for i in range(101):
progress.setValue(i);
sleep(0.05)
if progress.wasCanceled():
break
if __name__=="__main__":
import sys
app = QtGui.QApplication(sys.argv)
myapp = Test()
myapp.show()
sys.exit(app.exec_())

PyQt4 connect to signal "textValueChanged()"

I have a app that uses PyQt4 for GUI. But having some issues with connecting to signals.
I made a button like this
self.button=QtGui.QPushButton("Load File")
QObject.connect( self.button, SIGNAL('clicked ()'), self.clicked )
And it perfectly fires the following function:
def clicked(self):
So in the same manner i made a input element. However the input element signal does not fire when i change the text.
self.filter=QtGui.QInputDialog() #Create the Input Dialog
self.filter.setInputMode (self.filter.InputMode.TextInput ) #Change the input type to text
self.filter.setOption(self.filter.InputDialogOption.NoButtons,True) #I don't need the buttons so i have removed them
self.filter.setLabelText("Filter") #I change the label to "filter"
self.connect( self.filter, QtCore.SIGNAL("textValueChanged()"), self.filterUpdate ) #I connect to the signal textValueChanged() that should be fired when the text is changed and make it fire the filterUpdate() function
The following is never fired:
def filterUpdate(self):
print "Hello"
This works here:
from PyQt4 import QtCore, QtGui
import sys
app = QtGui.QApplication(sys.argv)
def filterUpdate():
print('!')
filter = QtGui.QInputDialog()
filter.setInputMode (filter.TextInput)
filter.setOption(filter.NoButtons, True)
filter.setLabelText("Filter")
filter.textValueChanged.connect(filterUpdate)
filter.show()
sys.exit(app.exec_())

Categories