I am very new to PyQt4 and was learning how to integrate it with my Python code at the back-end. The way I did it, the front-end looks just fine and takes all the input I need. When the processing starts, that is when the back-end scripts run, the window disappears and reappears when all my back end scripts have finished. The window is supposed to show the status of the on-going process (at the back end).
Please help me with this.
A Button on Win2 makes it switch to Win4 and that is when Win4 disappears and reappears once all the back end processing is done.
Code snippet:
class Win2(QtGui.QMainWindow, w2):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.move(500,200)
self.window1 = None
self.window4 = None
self.window5 = None
self.window6 = None
self.pushButton_2.clicked.connect(self.showWin4)
self.pushButton_9.clicked.connect(self.showWin5)
self.pushButton_5.clicked.connect(self.showWin6)
self.pushButton_8.clicked.connect(self.openIP)
self.pushButton_7.clicked.connect(self.opencred)
self.pushButton_6.clicked.connect(self.showWin1)
def openIP(self):
self.filename = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
#print filename
self.label_7.setText(self.filename)
def from_alldevicesrun(self):
#print check_port.all_ips
with open(self.filename, "rb") as csvfile:
iprow = csv.reader(csvfile, delimiter='\n')
for [ip] in iprow:
#print ip
from_alldevices.ips.append(ip)
csvfile.close()
from_alldevices.main()
def opencred(self):
self.filename1 = QtGui.QFileDialog.getOpenFileName(self, 'Open File', '.')
#print filename1
self.label_9.setText(self.filename1)
def see_cred(self):
'''
import __builtin__
__builtin__.x = self.filename1
import check_credentials_both
'''
cmd = ['python', 'c.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def showWin4(self):
self.close()
if self.window4 is None:
self.window4 = Win4()
self.window4.show()
self.window4.set_status_7('Ongoing')
self.from_alldevicesrun()
self.window4.set_status_7('Done')
self.window4.set_status_13('Ongoing')
self.see_cred()
self.window4.set_status_13('Done')
self.window4.set_status_8('Ongoing')
self.window4.get_data_from_server()
self.window4.set_status_8('Done')
self.window4.set_status_9('Ongoing')
self.window4.SSH_into_nw()
self.window4.set_status_9('Done')
self.window4.set_status_10('Ongoing')
self.window4.extract_mac()
self.window4.extract_lldp()
self.window4.port_channel_change()
self.window4.final_algo()
self.window4.set_status_10('Done')
self.window4.showWin10()
def showWin5(self):
if self.window5 is None:
self.window5 = Win5(self)
self.window5.show()
def showWin6(self):
if self.window6 is None:
self.window6 = Win6(self)
self.window6.show()
def showWin1(self):
self.close()
if self.window1 is None:
self.window1 = Win1(self)
self.window1.show()
class Win4(QtGui.QDialog, w4):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
self.move(500,200)
self.window10 = None
self.pushButton.clicked.connect(self.show_graphandWin8)
self.pushButton_2.clicked.connect(self.showWin10)
self.window8 = None
def show_graphandWin8(self):
#self.close()
if self.window8 is None:
self.window8 = Win8(self)
self.window8.show()
cmd = ['python', 'dc.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def set_status_7(self,text):
self.label_7.setText(text)
def set_status_8(self,text):
self.label_8.setText(text)
def set_status_9(self,text):
self.label_9.setText(text)
def set_status_10(self,text):
self.label_10.setText(text)
def set_status_13(self,text):
self.label_13.setText(text)
def get_data_from_server(self):
get_data_from_servers.main()
def SSH_into_nw(self):
import SSH_and_telnet_nw
SSH_and_telnet_nw.main()
def extract_mac(self):
cmd = ['python', '123.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def extract_lldp(self):
cmd = ['python', 'qwe.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def port_channel_change(self):
import change_to_port_channel
change_to_port_channel.main()
def final_algo(self):
cmd = ['python', 'abc.py' ]
cmd_out = subprocess.Popen( cmd , stdout=subprocess.PIPE).communicate()[0]
def showWin10(self):
if self.window10 is None:
self.window10 = Win10(self)
self.window10.show()
def main():
app = QtGui.QApplication(sys.argv)
form = Win2()
form.show()
sys.exit(app.exec_())
Thank you in advance.
You want to use hide() not close(). When you are calling self.close() you are making the QMainWindow stop and potentially be set for deletion. With hide() it will just make the Window invisible until you want to show() it again.
def showWin4(self):
self.hide() #This should be a hide not close
if self.window4 is None:
self.window4 = Win4()
self.window4.show()
Related
I have made a Desktop Application using Python and used PyQt5 and Pytube which could download video from youtube. When download is in Progress, I want to show user an animation. In Fact I did it, but when the file is getting downloaded the PyQt window seems like freezing and everything just gets paused until the download is complete. So, Does anyone know why is this happening? How do I fix it?
Here's the code snippet:
def download_created(self, qual): # Used in 'selection' method
selected_stream = yt.streams.get_by_resolution(qual)
self.progress_func()
try:
self.download_btn.setCurrentIndex(-1)
selected_stream.download(self.askLocation() + "/")
except:
pass
# This gets the quality that the user chooses
def selection(self):
global quality
quality = self.download_btn.currentText()
try:
self.download_created(quality) # Calls a method called 'download'
except:
self.start_anime()
# Fetching the details about the Link from Youtube
def download_youtube(self):
global check
if check != self.get_input():
check = self.get_input()
self.download_btn.clear()
enter_url = self.get_input()
try:
global yt
yt = pytube.YouTube(
enter_url,
on_progress_callback = on_progress,
on_complete_callback = self.complete_func)
self.start_anime()
except:
self.input_error()
VIDEO_TITLE = (yt.title)
global VIDEO_ID
VIDEO_ID = (yt.video_id)
videos = yt.streams.filter(mime_type="video/mp4", progressive="True")
# Display all the available qualities
for i in videos:
self.download_btn.addItem(i.resolution)
self.download_btn.currentIndexChanged.connect(self.selection)
You have to execute the time consuming tasks in another thread, for example in your case the task of getting the streams and downloading.
import sys
import threading
from functools import cached_property
from PyQt5 import QtCore, QtWidgets
import pytube
class QPyTube(QtCore.QObject):
initialized = QtCore.pyqtSignal(bool, str)
download_started = QtCore.pyqtSignal()
download_progress_changed = QtCore.pyqtSignal(int)
download_finished = QtCore.pyqtSignal()
def __init__(self, url):
super().__init__()
self._url = url
self._yt = None
self._mutex = threading.Lock()
threading.Thread(target=self._init, daemon=True).start()
#property
def url(self):
return self._url
#cached_property
def resolutions(self):
return list()
def _init(self):
with self._mutex:
self.resolutions.clear()
try:
self._yt = pytube.YouTube(
self.url,
on_progress_callback=self._on_progress,
on_complete_callback=self._on_complete,
)
streams = self._yt.streams.filter(mime_type="video/mp4", progressive="True")
except Exception as e:
self.initialized.emit(False, str(e))
return
with self._mutex:
self.resolutions = [stream.resolution for stream in streams]
self.initialized.emit(True, "")
def download(self, resolution, directory):
threading.Thread(
target=self._download, args=(resolution, directory), daemon=True
).start()
def _download(self, resolution, directory):
stream = self._yt.streams.get_by_resolution(resolution)
self.download_started.emit()
stream.download(directory)
def _on_progress(self, stream, chunk, bytes_remaining):
self.download_progress_changed.emit(
100 * (stream.filesize - bytes_remaining) // stream.filesize
)
def _on_complete(self, stream, filepath):
self.download_finished.emit()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.le_url = QtWidgets.QLineEdit("http://youtube.com/watch?v=2lAe1cqCOXo")
self.lbl_error = QtWidgets.QLabel()
self.btn_search = QtWidgets.QPushButton("Search")
self.cmb_resolutions = QtWidgets.QComboBox()
self.le_directory = QtWidgets.QLineEdit("")
self.btn_download = QtWidgets.QPushButton("Download")
self.pgb_download = QtWidgets.QProgressBar()
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QGridLayout(central_widget)
lay.addWidget(self.le_url, 0, 0)
lay.addWidget(self.btn_search, 0, 1)
lay.addWidget(self.cmb_resolutions, 1, 0)
lay.addWidget(self.le_directory, 1, 1)
lay.addWidget(self.btn_download, 1, 2)
lay.addWidget(self.pgb_download, 2, 0, 1, 3)
self.btn_download.setEnabled(False)
self._qpytube = None
self.btn_search.clicked.connect(self.handle_search_clicked)
self.btn_download.clicked.connect(self.handle_download_clicked)
def handle_search_clicked(self):
self.cmb_resolutions.clear()
self.btn_search.setEnabled(False)
self.btn_download.setEnabled(False)
self.lbl_error.clear()
self._qpytube = QPyTube(self.le_url.text())
self._qpytube.initialized.connect(self.handle_initialized)
self._qpytube.download_progress_changed.connect(self.pgb_download.setValue)
self._qpytube.download_started.connect(self.handle_download_started)
self._qpytube.download_finished.connect(self.handle_download_finished)
#QtCore.pyqtSlot(bool, str)
def handle_initialized(self, status, error=""):
if status:
self.cmb_resolutions.addItems(self._qpytube.resolutions)
self.btn_download.setEnabled(True)
else:
self.lbl_error.setText(error)
self.btn_search.setEnabled(True)
def handle_download_clicked(self):
self._qpytube.download(
self.cmb_resolutions.currentText(), self.le_directory.text()
)
self.btn_search.setEnabled(False)
self.btn_download.setEnabled(False)
self.le_directory.setEnabled(False)
def handle_download_started(self):
self.lbl_error.clear()
print("started")
def handle_download_finished(self):
self.pgb_download.setValue(100)
self.btn_search.setEnabled(True)
self.btn_download.setEnabled(True)
self.le_directory.setEnabled(True)
print("finished")
def main(args):
app = QtWidgets.QApplication(args)
w = MainWindow()
w.show()
app.exec_()
if __name__ == "__main__":
main(sys.argv)
I have made a Desktop Application using Python and used PyQt5 and Pytube which could download video from youtube. When download is in Progress, I want to show user an animation. In Fact I did it, but when the file is getting downloaded the PyQt window seems like freezing and everything just gets paused until the download is complete. So, Does anyone know why is this happening? How do I fix it?
Here's the code snippet:
def download_created(self, qual): # Used in 'selection' method
selected_stream = yt.streams.get_by_resolution(qual)
self.progress_func()
try:
self.download_btn.setCurrentIndex(-1)
selected_stream.download(self.askLocation() + "/")
except:
pass
# This gets the quality that the user chooses
def selection(self):
global quality
quality = self.download_btn.currentText()
try:
self.download_created(quality) # Calls a method called 'download'
except:
self.start_anime()
# Fetching the details about the Link from Youtube
def download_youtube(self):
global check
if check != self.get_input():
check = self.get_input()
self.download_btn.clear()
enter_url = self.get_input()
try:
global yt
yt = pytube.YouTube(
enter_url,
on_progress_callback = on_progress,
on_complete_callback = self.complete_func)
self.start_anime()
except:
self.input_error()
VIDEO_TITLE = (yt.title)
global VIDEO_ID
VIDEO_ID = (yt.video_id)
videos = yt.streams.filter(mime_type="video/mp4", progressive="True")
# Display all the available qualities
for i in videos:
self.download_btn.addItem(i.resolution)
self.download_btn.currentIndexChanged.connect(self.selection)
You have to execute the time consuming tasks in another thread, for example in your case the task of getting the streams and downloading.
import sys
import threading
from functools import cached_property
from PyQt5 import QtCore, QtWidgets
import pytube
class QPyTube(QtCore.QObject):
initialized = QtCore.pyqtSignal(bool, str)
download_started = QtCore.pyqtSignal()
download_progress_changed = QtCore.pyqtSignal(int)
download_finished = QtCore.pyqtSignal()
def __init__(self, url):
super().__init__()
self._url = url
self._yt = None
self._mutex = threading.Lock()
threading.Thread(target=self._init, daemon=True).start()
#property
def url(self):
return self._url
#cached_property
def resolutions(self):
return list()
def _init(self):
with self._mutex:
self.resolutions.clear()
try:
self._yt = pytube.YouTube(
self.url,
on_progress_callback=self._on_progress,
on_complete_callback=self._on_complete,
)
streams = self._yt.streams.filter(mime_type="video/mp4", progressive="True")
except Exception as e:
self.initialized.emit(False, str(e))
return
with self._mutex:
self.resolutions = [stream.resolution for stream in streams]
self.initialized.emit(True, "")
def download(self, resolution, directory):
threading.Thread(
target=self._download, args=(resolution, directory), daemon=True
).start()
def _download(self, resolution, directory):
stream = self._yt.streams.get_by_resolution(resolution)
self.download_started.emit()
stream.download(directory)
def _on_progress(self, stream, chunk, bytes_remaining):
self.download_progress_changed.emit(
100 * (stream.filesize - bytes_remaining) // stream.filesize
)
def _on_complete(self, stream, filepath):
self.download_finished.emit()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.le_url = QtWidgets.QLineEdit("http://youtube.com/watch?v=2lAe1cqCOXo")
self.lbl_error = QtWidgets.QLabel()
self.btn_search = QtWidgets.QPushButton("Search")
self.cmb_resolutions = QtWidgets.QComboBox()
self.le_directory = QtWidgets.QLineEdit("")
self.btn_download = QtWidgets.QPushButton("Download")
self.pgb_download = QtWidgets.QProgressBar()
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QGridLayout(central_widget)
lay.addWidget(self.le_url, 0, 0)
lay.addWidget(self.btn_search, 0, 1)
lay.addWidget(self.cmb_resolutions, 1, 0)
lay.addWidget(self.le_directory, 1, 1)
lay.addWidget(self.btn_download, 1, 2)
lay.addWidget(self.pgb_download, 2, 0, 1, 3)
self.btn_download.setEnabled(False)
self._qpytube = None
self.btn_search.clicked.connect(self.handle_search_clicked)
self.btn_download.clicked.connect(self.handle_download_clicked)
def handle_search_clicked(self):
self.cmb_resolutions.clear()
self.btn_search.setEnabled(False)
self.btn_download.setEnabled(False)
self.lbl_error.clear()
self._qpytube = QPyTube(self.le_url.text())
self._qpytube.initialized.connect(self.handle_initialized)
self._qpytube.download_progress_changed.connect(self.pgb_download.setValue)
self._qpytube.download_started.connect(self.handle_download_started)
self._qpytube.download_finished.connect(self.handle_download_finished)
#QtCore.pyqtSlot(bool, str)
def handle_initialized(self, status, error=""):
if status:
self.cmb_resolutions.addItems(self._qpytube.resolutions)
self.btn_download.setEnabled(True)
else:
self.lbl_error.setText(error)
self.btn_search.setEnabled(True)
def handle_download_clicked(self):
self._qpytube.download(
self.cmb_resolutions.currentText(), self.le_directory.text()
)
self.btn_search.setEnabled(False)
self.btn_download.setEnabled(False)
self.le_directory.setEnabled(False)
def handle_download_started(self):
self.lbl_error.clear()
print("started")
def handle_download_finished(self):
self.pgb_download.setValue(100)
self.btn_search.setEnabled(True)
self.btn_download.setEnabled(True)
self.le_directory.setEnabled(True)
print("finished")
def main(args):
app = QtWidgets.QApplication(args)
w = MainWindow()
w.show()
app.exec_()
if __name__ == "__main__":
main(sys.argv)
I am trying to read 2 different files at the same time using pyqt and threads but only one thread gets run out of the two. My code has 2 thread classes and each are responsible for reading their assigned files. How can I achieve this?
Here is what I've tried:
import sys
from PyQt4 import QtCore, QtGui
import subprocess
from time import sleep
class Thread1(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
def file_len(self):
p = subprocess.Popen(['wc', '-l', 'file1.txt'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result, err = p.communicate()
if p.returncode != 0:
raise IOError(err)
return int(result.strip().split()[0]) #returns 600 lines
def run(self):
self.emit(QtCore.SIGNAL('updateProgressBar(int)'), 0) ## Reset progressbar value
file_in = "file1.txt"
loading = 0
x = float(100) / self.file_len()
with open(file_in) as f:
for line in f:
loading += x
print line
self.emit(QtCore.SIGNAL('updateProgressBar(int)'), loading)
sleep(0.15)
class Thread2(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
def file_len(self):
p = subprocess.Popen(['wc', '-l', 'file2.txt'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result, err = p.communicate()
if p.returncode != 0:
raise IOError(err)
return int(result.strip().split()[0]) #returns 2500 lines
def run(self):
self.emit(QtCore.SIGNAL('updateProgressBar(int)'), 0) ## Reset progressbar value
file_in = "file2.txt"
loading = 0
x = float(100) / self.file_len()
with open(file_in) as f:
for line in f:
loading += x
print line
self.emit(QtCore.SIGNAL('updateProgressBar(int)'), loading)
sleep(0.001)
class AppView(QtGui.QDialog):
def __init__(self, parent=None):
super(AppView, self).__init__(parent)
self.resize(400, 400)
self.buttonStart = QtGui.QPushButton(self)
self.buttonStart.setText("Start")
self.buttonStart.clicked.connect(self.start)
self.progress = QtGui.QProgressBar(self)
self.progress2 = QtGui.QProgressBar(self)
verticalLayout = QtGui.QVBoxLayout(self)
verticalLayout.addWidget(self.buttonStart)
verticalLayout.addWidget(self.progress)
verticalLayout.addWidget(self.progress2)
self.progressView = Thread1()
self.progressView2 = Thread2()
self.connect(self.progressView, QtCore.SIGNAL("updateProgressBar(int)"), self.updateProgressBar)
self.connect(self.progressView2, QtCore.SIGNAL("updateProgressBar2(int)"), self.updateProgressBar2)
self.start()
def updateProgressBar(self, percent):
self.progress.setValue(percent)
def updateProgressBar2(self, percent):
self.progress2.setValue(percent)
def start(self):
self.progressView.start()
self.progressView2.start()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
appview = AppView()
appview.show()
sys.exit(app.exec_())
Perhaps the method run of thread2 must call updateProgressBar2, not updateProgressBar?
I have this little program I wrote, In it there is a class of methods, and a class that build the window (only one).
from Tkinter import *
from tkMessageBox import *
import socket
import platform ,sys
import subprocess
from multiprocessing.pool import ThreadPool
import Queue
import threading
class Methods(object):
def __init__(self):
#TODO : implement
pass
def getHostName(self):
try:
return socket.gethostname()
except:
return "ERROR :Could'nt get Hostname"
def getOperatingSystem(self):
try:
return platform.system() + " " + platform.release() + " " + platform.version() + " " + sys.getwindowsversion()[4]
except:
return "ERROR :Could'nt get Operating System"
def getHotFixes(self,queue):
try:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
myProcess = subprocess.Popen(
"wmic qfe get HotFixID, InstalledOn",
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
startupinfo = startupinfo)
out, error = myProcess.communicate()
full_list = out.splitlines()
result = ""
for item in full_list:
if item != "" and item != " ":
result += "%s \n" % item
out_number = len(result.splitlines()) - 1
a = "There Are %s Microsoft HotFixes Updates \n\n%s" % (out_number , result)
queue.put(a)
except:
return "ERROR :Could'nt get HotFixes"
#VISUAL
#This class will have an instance of Methods and call every action by itself.
class MainWindow(object):
def __init__(self):
self.root = Tk()
self.root.title('SAAP')
self.root.geometry('610x440+100+100')
#self.root.resizable(0,0)
self.methods = Methods()
def openHostName():
disableAllButtons(self)
result = self.methods.getHostName()
print result
self.textLabelString.set("Host Name")
self.textBox.config(state=NORMAL)
self.textBox.delete("1.0",END)
self.textBox.insert(INSERT,result)
self.textBox.config(state=DISABLED)
enableAllButtons(self)
def openOperatingSystem():
disableAllButtons(self)
result = self.methods.getOperatingSystem()
print result
self.textLabelString.set("Operating System")
self.textBox.config(state=NORMAL)
self.textBox.delete("1.0",END)
self.textBox.insert(INSERT,result)
self.textBox.config(state=DISABLED)
enableAllButtons(self)
def openHotFixes():
queue = Queue.Queue()
thread_ = threading.Thread(
target = self.methods.getHotFixes,
name='Thread1',
args=[queue],
)
thread_.start()
thread_.join()
result = queue.get()
disableAllButtons(self)
self.textLabelString.set("Microsoft Hotfixes")
self.textBox.config(state=NORMAL)
self.textBox.delete("1.0",END)
self.textBox.insert(INSERT,result)
self.textBox.config(state=DISABLED)
enableAllButtons(self)
#items decleration
self.actionLabel = Label(self.root, text = 'Actions',bg='blue',fg='white')
self.button1 = Button(self.root, text = 'Host Name' , command=openHostName)
self.button2 = Button(self.root, text = 'Operating System' , command = openOperatingSystem)
self.button3 = Button(self.root, text = 'Microsoft HotFixes' , command = openHotFixes)
self.button4 = Button(self.root, text = 'N4')
self.button5 = Button(self.root, text = 'Fi5o')
self.button6 = Button(self.root, text = 'C6y')
self.button7 = Button(self.root, text = '7')
self.button8 = Button(self.root, text = '8y')
self.button9 = Button(self.root, text = 'R9s')
self.button10 = Button(self.root, text = '10t')
self.button11 = Button(self.root, text = 'I11s')
self.textLabelString = StringVar()
self.textLabel = Label(self.root,bg='black',fg='white',width=60,textvariable=self.textLabelString)
self.textLabelString.set("Output")
self.textBox = Text(self.root,width=52)
self.textBox.insert(INSERT,"Here's the output")
self.textBox.config(state=DISABLED)
self.scrollBar = Scrollbar(self.root)
self.scrollBar.config(command=self.textBox.yview)
self.textBox.config(yscrollcommand=self.scrollBar.set)
#items placing
self.actionLabel.grid(row=0,column=0,sticky=W+E+N+S,pady=5)
self.button1.grid(row=1,column=0,padx=5,pady=5,sticky=W+E)
self.button2.grid(row=2,column=0,padx=5,pady=5,sticky=W+E)
self.button3.grid(row=3,column=0,padx=5,pady=5,sticky=W+E)
self.button4.grid(row=4,column=0,padx=5,pady=5,sticky=W+E)
self.button5.grid(row=5,column=0,padx=5,pady=5,sticky=W+E)
self.button6.grid(row=6,column=0,padx=5,pady=5,sticky=W+E)
self.button7.grid(row=7,column=0,padx=5,pady=5,sticky=W+E)
self.button8.grid(row=8,column=0,padx=5,pady=5,sticky=W+E)
self.button9.grid(row=9,column=0,padx=5,pady=5,sticky=W+E)
self.button10.grid(row=10,column=0,padx=5,pady=5,sticky=W+E)
self.button11.grid(row=11,column=0,padx=5,pady=5,sticky=W+E)
self.textLabel.grid(row=0,column=1,padx=10,pady=5)
self.textBox.grid(row=1,column=1,rowspan=11,pady=5)
self.scrollBar.grid(row=1,column=2,rowspan=11,sticky=N+S)
def disableAllButtons(self):
self.button1['state'] = DISABLED
self.button2['state'] = DISABLED
self.button3['state'] = DISABLED
self.button4['state'] = DISABLED
self.button5['state'] = DISABLED
self.button6['state'] = DISABLED
self.button7['state'] = DISABLED
self.button8['state'] = DISABLED
self.button9['state'] = DISABLED
self.button10['state'] = DISABLED
self.button11['state'] = DISABLED
def enableAllButtons(self):
self.button1['state'] = NORMAL
self.button2['state'] = NORMAL
self.button3['state'] = NORMAL
self.button4['state'] = NORMAL
self.button5['state'] = NORMAL
self.button6['state'] = NORMAL
self.button7['state'] = NORMAL
self.button8['state'] = NORMAL
self.button9['state'] = NORMAL
self.button10['state'] = NORMAL
self.button11['state'] = NORMAL
def main():
mainw = MainWindow()
mainw.root.mainloop()
if __name__ == "__main__":
main()
Now , My problem is when I press a button it needs to do something and then the output should appear on screen.
BUT, and here comes the but --
when the action takes a bit, it freezes the program until the action is done.
I want to make the program treat maybe the action as a different thread so it won't freeze.
I tried some stuff but it did not worked for me unfortunately ...
Any Help ?
Appreciated!
It is ok to execute your actions in separate threads, however you need to implement a
mechanism for signaling to your main thread (where Tk's loop is running) when actions
are finished, and to get the result(s).
One approach is to have a proper Action class, creating thread objects ; you pass
the method to execute and its arguments, then you start the thread - beforehand,
you register a callback that will be called in your Tk loop when action is finished.
In order to pass results from the thread to the callback, a Queue can be used:
import functools
class Action(threading.Thread):
def __init__(self, method, *args):
threading.Thread.__init__(self)
self.daemon = True
self.method=method
self.args=args
self.queue=Queue.Queue()
def run(self):
self.queue.put(self.method(*self.args))
def register_callback(self, tkroot, callback):
# to be called by Tk's main thread,
# will execute the callback in the Tk main loop
try:
result = self.queue.get_nowait()
except:
# set a timer, to check again for results within 100 milliseconds
tkroot.after(100, functools.partial(self.register_callback,
tkroot, callback))
else:
return callback(result)
EDIT: modification of the original example to show how to apply this to the getHotFixes
method
As an example, here is how to change getHotFixes accordingly:
class Methods(object):
...
def getHotFixes(self):
try:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
myProcess = subprocess.Popen("wmic qfe get HotFixID, InstalledOn",
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
startupinfo = startupinfo)
out, error = myProcess.communicate()
full_list = out.splitlines()
result = ""
for item in full_list:
if item != "" and item != " ":
result += "%s \n" % item
out_number = len(result.splitlines()) - 1
return "There Are %s Microsoft HotFixes Updates \n\n%s" % (out_number , result)
except:
return "ERROR :Could'nt get HotFixes"
Finally, in MainWindow you just need to call the getHotFixes method, register
a callback to do something useful with the result when it's finished using
register_callback and call start() to start the Action thread:
class MainWindow(object):
def __init__(self):
self.root = Tk()
...
def openHotFixes():
disableAllButtons(self)
action = Action(self.methods.getHotFixes)
action.register_callback(self.root, openHotFixesDone)
action.start()
def openHotFixesDone(result):
self.textLabelString.set("Microsoft Hotfixes")
self.textBox.config(state=NORMAL)
self.textBox.delete("1.0",END)
self.textBox.insert(INSERT,result)
self.textBox.config(state=DISABLED)
enableAllButtons(self)
Hope this helps.
I want to display a log file in a dialogue with three buttons.I can append each line to the textBrowser with the following code, but when I try to append the whole text the GUI freezes.
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import os
import sys
import time
import UI_logs
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class WorkThread(QtCore.QThread):
def __init__(self):
QtCore.QThread.__init__(self)
def __del__(self):
self.wait()
def run(self):
#Reading and appending the whole text
# logs = open('logs.txt', 'r').read()
# self.emit(QtCore.SIGNAL('update(QString)'), str(logs))
#Reading and appending line by line
logs = open('logs.txt', 'r').readlines()
for line in logs:
self.emit(QtCore.SIGNAL('update(QString)'), str(line))
time.sleep(0.1)
self.terminate()
class Logs(QtGui.QDialog):
def __init__(self, parent=None):
super(Logs, self).__init__(parent)
self.ui = UI_logs.Ui_Dialog()
self.ui.setupUi(self)
self.load_logs()
QtCore.QObject.connect(self.ui.pushButton_3, QtCore.SIGNAL(_fromUtf8("clicked()")), self.clear_logs)
QtCore.QObject.connect(self.ui.pushButton_4, QtCore.SIGNAL(_fromUtf8("clicked()")), self.load_logs)
QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.export)
def display_logs(self, text):
self.ui.textBrowser.append(text)
self.ui.textBrowser.update()
self.ui.textBrowser.moveCursor(QtGui.QTextCursor.End)
def load_logs(self):
self.workThread = WorkThread()
QtCore.QObject.connect(self.workThread, QtCore.SIGNAL("update(QString)"), self.display_logs)
self.workThread.start()
def clear_logs(self):
try:
os.remove('logs.txt')
self.ui.textBrowser.clear()
info_msg = "Your logs file has been deleted."
info_reply = QtGui.QMessageBox.warning(None, 'Logs Notification', info_msg, QtGui.QMessageBox.Ok)
except:
info_msg = "Your logs file can not be deleted."
info_reply = QtGui.QMessageBox.warning(None, 'Logs Notification', info_msg, QtGui.QMessageBox.Ok)
def export(self):
log_text = self.ui.textBrowser.toPlainText()
if log_text:
filename = QtGui.QFileDialog.getSaveFileName(None, 'Export logs as',
'.', 'Text Documents (*.txt)')
if filename:
fname = open(filename, 'w')
fname.write(log_text)
fname.close()
info_msg = "Your logs file has been exported successfully."
info_reply = QtGui.QMessageBox.warning(None, 'Logs Notification', info_msg, QtGui.QMessageBox.Ok)
else:
warning_title = 'Export Warning'
warning_text = 'There is nothing in the logs to export.'
QtGui.QMessageBox.warning(None, warning_title,
warning_text, QtGui.QMessageBox.Ok)
app = QApplication(sys.argv)
app.setApplicationName('MyWindow')
window = Logs()
window.show()
sys.exit(app.exec_())
Try with one of those 3 commented lines:
logs = open('logs.txt', 'r').read()
#logs = logs.encode('utf-8')
#logs = QString(logs)
#logs = unicode(QString(logs))
self.emit(QtCore.SIGNAL('update(QString)'), str(logs))
also, try them without converting logs to string:
self.emit(QtCore.SIGNAL('update(QString)'), logs)
I don't have import UI_logs so I can't test it, but one of those should work...