How can I use the window handle to screenshot a running instance of Notepad? I already figured out how to successfully screenshot a widget within the python dialog itself. I have also figured out how to get the handle of the running notepad window. I'm stuck on trying to capture the screenshot of the window using the handle.
import os, sys
from PySide import QtGui, QtCore
import ctypes
class GuiCaptureWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(GuiCaptureWindow, self).__init__(parent)
self.resize(250, 100)
self.setWindowTitle('GUI Capture')
# console
self.ui_capture = QtGui.QPushButton('Capture')
main_layout = QtGui.QGridLayout()
main_layout.addWidget(self.ui_capture)
main_widget = QtGui.QWidget()
main_widget.setLayout(main_layout)
self.setCentralWidget(main_widget)
# signals
self.ui_capture.clicked.connect(self.capture)
def getRelativeFrameGeometry(self, widget):
g = widget.geometry()
fg = widget.frameGeometry()
return fg.translated(-g.left(),-g.top())
def screenCaptureWidget(self, widget, filename, fileformat='.png'):
rfg = self.getRelativeFrameGeometry(widget)
pixmap = QtGui.QPixmap.grabWindow(widget.winId(),
rfg.left(), rfg.top(),
rfg.width(), rfg.height())
filepath = os.path.abspath(filename + fileformat)
pixmap.save(filepath)
os.system("start " + filepath)
def capture(self):
self.collect_window_titles()
self.screenCaptureWidget(self.ui_capture, 'test')
def collect_window_titles(self):
EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible
apps = []
def foreach_window(hwnd, lParam):
if IsWindowVisible(hwnd):
length = GetWindowTextLength(hwnd)
buff = ctypes.create_unicode_buffer(length + 1)
GetWindowText(hwnd, buff, length + 1)
if buff.value:
apps.append({'title': buff.value, 'handle': hwnd})
return True
EnumWindows(EnumWindowsProc(foreach_window), 0)
for app in apps:
print app
if app['title'] == 'Untitled - Notepad':
print 'CAPTURE'
return
def main():
app = QtGui.QApplication(sys.argv)
ex = GuiCaptureWindow()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Related
I want to play sounds with QtMultimedia.
In the case of QMediaPlayer, I could play mp3 file , it is made from gTTS.
(I think it is okay but I don't like the file remains unless I excute codes for deleting it.)
I make a mp3 file with gTTS module and I want to play sounds with the buffer directly.
It seems that I can make a valid object but QAudioOutput doesn't do anything.
I seriarize the mp3 file into a database and fetch it when I like.
What is short of my code?
Here is the excerpt of my original Code.
In my original code, the buffer data is in Qt.UserRole + x and I can take them whenever.
The playlist is constucted with QTableWidget and QTableWidgetItem.
from PySide2 import QtCore
from PySide2 import QtWidgets
from PySide2 import QtMultimedia
import os
import PySide2
import sys
dirname = os.path.dirname(PySide2.__file__)
plugin_path = os.path.join(dirname, 'plugins', 'platforms')
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path
import gtts
def main():
if QtWidgets.QApplication.instance() is not None:
app = QtWidgets.QApplication.instance()
else:
app = QtWidgets.QApplication([])
widget = QtWidgets.QTableWidget()
widget.setColumnCount(2)
text = "hello"
lang = "en"
onsei = gtts.gTTS(text=text, lang=lang)
buf = QtCore.QBuffer()
buf.setOpenMode( QtCore.QIODevice.WriteOnly)
onsei.write_to_fp(buf)
buf.close()
if not widget.rowCount():
widget.setRowCount(1)
else:
widget.insertRow(1)
nitem = QtWidgets.QTableWidgetItem()
nitem.setText(str(widget.rowCount()))
item = QtWidgets.QTableWidgetItem()
item.setText("{0}_tts_lang_{1}.mp3".format(text, lang))
item.setData(QtCore.Qt.UserRole+1, buf.data())
variant = item.data(QtCore.Qt.UserRole+1)
format = QtMultimedia.QAudioFormat()
format.setSampleRate(8000)
format.setChannelCount(1)
format.setSampleSize(16)
format.setCodec("audio/pcm")
format.setByteOrder(QtMultimedia.QAudioFormat.LittleEndian)
format.setSampleType(QtMultimedia.QAudioFormat.UnSignedInt)
buf = QtCore.QBuffer()
buf.setData(variant)
buf.open(QtCore.QIODevice.ReadOnly)
buf.seek(0)
audio = QtMultimedia.QAudioOutput(format, app)
audio.setVolume(0.5)
audio.setBufferSize(buf.size())
audio.start(buf)
buf.close()
print(67)
# sys.exit(QtWidgets.QApplication.exec_())
sys.exit()
if __name__ == "__main__":
main()
Instead of using QAudioOutput you could use QMediaPlayer:
import sys
import threading
import uuid
from PySide2 import QtCore, QtGui, QtWidgets, QtMultimedia
import gtts
IdentifierRole = QtCore.Qt.UserRole
DataRole = QtCore.Qt.UserRole + 1
DownLoadRole = QtCore.Qt.UserRole + 2
ActiveRole = QtCore.Qt.UserRole + 3
class BackgroundColorDelegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super().initStyleOption(option, index)
color = None
if index.data(DownLoadRole):
color = QtGui.QColor("green")
if index.data(ActiveRole):
color = QtGui.QColor("red")
if color:
option.backgroundBrush = color
class DownLoader(QtCore.QObject):
downloaded = QtCore.Signal(str, QtCore.QByteArray)
def start(self, identifier, text, lang):
threading.Thread(
target=self._execute, args=(identifier, text, lang), daemon=True
).start()
def _execute(self, identifier, text, lang):
tts = gtts.gTTS(text=text, lang=lang)
buf = QtCore.QBuffer()
buf.open(QtCore.QBuffer.ReadWrite)
tts.write_to_fp(buf)
self.downloaded.emit(identifier, buf.data())
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.player = QtMultimedia.QMediaPlayer()
self.current_buff = QtCore.QBuffer()
self.tablewidget = QtWidgets.QTableWidget(
0,
2,
selectionBehavior=QtWidgets.QAbstractItemView.SelectRows,
editTriggers=QtWidgets.QAbstractItemView.NoEditTriggers,
)
delegate = BackgroundColorDelegate(self.tablewidget)
self.tablewidget.setItemDelegateForColumn(0, delegate)
self.tablewidget.itemClicked.connect(self.on_item_clicked)
self.setCentralWidget(self.tablewidget)
self.add_row("hello", "en")
self.add_row("world", "en")
def add_row(self, text, lang):
it = QtWidgets.QTableWidgetItem("{0}_tts_lang_{1}.mp3".format(text, lang))
identifier = str(uuid.uuid4())
it.setData(IdentifierRole, identifier)
downloader = DownLoader(self)
downloader.start(identifier, text, lang)
downloader.downloaded.connect(self.on_downloaded)
downloader.downloaded.connect(downloader.deleteLater)
row = self.tablewidget.rowCount()
self.tablewidget.insertRow(row)
self.tablewidget.setItem(row, 0, it)
#QtCore.Slot(str, QtCore.QByteArray)
def on_downloaded(self, identifier, data):
model = self.tablewidget.model()
indexes = model.match(
model.index(0, 0), IdentifierRole, identifier, flags=QtCore.Qt.MatchExactly
)
if indexes:
item = self.tablewidget.itemFromIndex(indexes[0])
item.setData(DataRole, data)
item.setData(DownLoadRole, True)
#QtCore.Slot("QTableWidgetItem*")
def on_item_clicked(self, item):
self.player.stop()
self.current_buff.close()
data = item.data(DataRole)
if not data:
return
self.current_buff.setData(data)
self.current_buff.open(QtCore.QIODevice.ReadOnly)
self.player.setMedia(QtMultimedia.QMediaContent(), self.current_buff)
self.player.play()
for row in range(self.tablewidget.rowCount()):
it = self.tablewidget.item(row, 0)
it.setData(ActiveRole, it is item)
def main():
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication([])
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
i'm trying to fix problem in my program and this problem is when i start download video the program not responding and i can't see also progress bar move so i tried used threading module but i can't fix problem so how i can fix problem
From this code I can download the video and send the data to another function to retrieve information that I use to connect it to the progress bar
def video(self):
video_url = self.lineEdit_4.text()
video_save = self.lineEdit_3.text()
pafy_video = pafy.new(video_url)
type_video = pafy_video.videostreams
quality = self.comboBox.currentIndex()
start_download = type_video[quality].download(filepath=video_save,callback=self.video_progressbar)
This code is received information from video function to connect with progress bar
def video_progressbar(self,total, recvd, ratio, rate, eta):
self.progressBar_2.setValue(ratio * 100)
I use;python3.5 pyqt5 pafy
One way to move to another thread is to create a QObject that lives in another thread and execute that task in a slot. And that slot must be invoked through QMetaObject::invokeMethod or a signal.
with QThread and QMetaObject::invokeMethod:
import pafy
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
self.le_url = QtWidgets.QLineEdit("https://www.youtube.com/watch?v=bMt47wvK6u0")
path = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DownloadLocation)
self.le_output = QtWidgets.QLineEdit(path)
self.btn_quality = QtWidgets.QPushButton("Get qualities")
self.combo_quality = QtWidgets.QComboBox()
self.btn_download = QtWidgets.QPushButton("Download")
self.progressbar = QtWidgets.QProgressBar(maximum=100)
self.downloader = DownLoader()
thread = QtCore.QThread(self)
thread.start()
self.downloader.moveToThread(thread)
self.btn_quality.clicked.connect(self.on_clicked_quality)
self.btn_download.clicked.connect(self.download)
self.btn_download.setDisabled(True)
self.downloader.progressChanged.connect(self.progressbar.setValue)
self.downloader.qualitiesChanged.connect(self.update_qualityes)
self.downloader.finished.connect(self.on_finished)
form_lay = QtWidgets.QFormLayout(central_widget)
form_lay.addRow("Url: ", self.le_url)
form_lay.addRow(self.btn_quality)
form_lay.addRow("qualities: ", self.combo_quality)
form_lay.addRow("Output: ", self.le_output)
form_lay.addRow(self.btn_download)
form_lay.addRow(self.progressbar)
#QtCore.pyqtSlot()
def on_finished(self):
self.update_disables(False)
#QtCore.pyqtSlot()
def on_clicked_quality(self):
video_url = self.le_url.text()
QtCore.QMetaObject.invokeMethod(self.downloader, "get_qualities",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(str, video_url))
#QtCore.pyqtSlot(list)
def update_qualityes(self, types_of_video):
for t in types_of_video:
self.combo_quality.addItem(str(t), t)
self.btn_download.setDisabled(False)
#QtCore.pyqtSlot()
def download(self):
video_save = self.le_output.text()
d = self.combo_quality.currentData()
QtCore.QMetaObject.invokeMethod(self.downloader, "start_download",
QtCore.Qt.QueuedConnection,
QtCore.Q_ARG(object, d),
QtCore.Q_ARG(str, video_save))
self.update_disables(True)
def update_disables(self, state):
self.combo_quality.setDisabled(state)
self.btn_quality.setDisabled(state)
self.le_output.setDisabled(state)
self.le_url.setDisabled(state)
self.btn_download.setDisabled(not state)
class DownLoader(QtCore.QObject):
progressChanged = QtCore.pyqtSignal(int)
qualitiesChanged = QtCore.pyqtSignal(list)
finished = QtCore.pyqtSignal()
#QtCore.pyqtSlot(str)
def get_qualities(self, video_url):
pafy_video = pafy.new(video_url)
types_of_video = pafy_video.allstreams # videostreams
self.qualitiesChanged.emit(types_of_video)
#QtCore.pyqtSlot(object, str)
def start_download(self, d, filepath):
d.download(filepath=filepath, callback=self.callback)
def callback(self, total, recvd, ratio, rate, eta):
val = int(ratio * 100)
self.progressChanged.emit(val)
if val == 100:
self.finished.emit()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(320, 480)
w.show()
sys.exit(app.exec_())
with threading.Thread:
import pafy
import threading
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
qualitiesChanged = QtCore.pyqtSignal(list)
progressChanged = QtCore.pyqtSignal(int)
finished = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
self.le_url = QtWidgets.QLineEdit("https://www.youtube.com/watch?v=bMt47wvK6u0")
path = QtCore.QStandardPaths.writableLocation(QtCore.QStandardPaths.DownloadLocation)
self.le_output = QtWidgets.QLineEdit(path)
self.btn_quality = QtWidgets.QPushButton("Get qualities")
self.combo_quality = QtWidgets.QComboBox()
self.btn_download = QtWidgets.QPushButton("Download")
self.progressbar = QtWidgets.QProgressBar(maximum=100)
self.btn_quality.clicked.connect(self.on_clicked_quality)
self.btn_download.clicked.connect(self.download)
self.btn_download.setDisabled(True)
self.progressChanged.connect(self.progressbar.setValue)
self.qualitiesChanged.connect(self.update_qualityes)
self.finished.connect(self.on_finished)
form_lay = QtWidgets.QFormLayout(central_widget)
form_lay.addRow("Url: ", self.le_url)
form_lay.addRow(self.btn_quality)
form_lay.addRow("qualities: ", self.combo_quality)
form_lay.addRow("Output: ", self.le_output)
form_lay.addRow(self.btn_download)
form_lay.addRow(self.progressbar)
#QtCore.pyqtSlot()
def on_finished(self):
self.update_disables(False)
#QtCore.pyqtSlot()
def on_clicked_quality(self):
video_url = self.le_url.text()
threading.Thread(target=self.get_qualities, args=(video_url,)).start()
def get_qualities(self, video_url):
pafy_video = pafy.new(video_url)
types_of_video = pafy_video.allstreams # videostreams
self.qualitiesChanged.emit(types_of_video)
#QtCore.pyqtSlot(list)
def update_qualityes(self, types_of_video):
for t in types_of_video:
self.combo_quality.addItem(str(t), t)
self.btn_download.setDisabled(False)
#QtCore.pyqtSlot()
def download(self):
video_save = self.le_output.text()
d = self.combo_quality.currentData()
threading.Thread(target=d.download, kwargs={'filepath': video_save, 'callback': self.callback}, daemon=True).start()
def callback(self, total, recvd, ratio, rate, eta):
print(ratio)
val = int(ratio * 100)
self.progressChanged.emit(val)
if val == 100:
self.finished.emit()
def update_disables(self, state):
self.combo_quality.setDisabled(state)
self.btn_quality.setDisabled(state)
self.le_output.setDisabled(state)
self.le_url.setDisabled(state)
self.btn_download.setDisabled(not state)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(320, 480)
w.show()
sys.exit(app.exec_())
I am currently making an application with PyQt5 and I am trying to find a way to refresh the main window when the QWidget it calls is closed.
My main window page looks like this:
import sys
import glob
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from addClass import addClass
class TeacherMain(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.initUI()
def initUI(self):
x = 30
y = 80
buttonContainer = QLabel(self)
buttonContainer.setStyleSheet("background-color: #5D4A41;")
buttonContainer.move(20, 70)
buttonContainer.resize(1240, 550)
buttonContainer.show()
classes = glob.glob("Folder/*.csv")
classes = [j.strip("Folder/") for j in [i.strip('.csv') for i in classes]]
for k in classes:
classButton = QPushButton(k, self)
classButton.move(x, y)
classButton.setStyleSheet("background-color: green;")
classButton.resize(143, 143)
classButton.clicked.connect(self.viewClass)
x += 153 ## Increase value of x.
if x >= 1235:
y += 153
x = 30
addClass = QPushButton("Add Class...", self)
addClass.move(x, y)
addClass.resize(143, 143)
addClass.clicked.connect(self.createClass)
quit = QPushButton("Quit", self)
quit.setStyleSheet("background-color: white;")
quit.move(630, 645)
self.setStyleSheet("background-color: #AD9A90;")
self.setWindowTitle("SheikhCoin Teacher")
self.setFixedSize(1280, 690)
self.show()
def createClass(self):
self.new_window = addClass()
self.new_window.show()
def main():
app = QApplication(sys.argv)
main = TeacherMain()
main.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
And my QWidget looks like this:
class addClass(QWidget):
def __init__(self):
QWidget.__init__(self)
self.initUI()
def initUI(self, granted):
className = QLabel("Class Name", self)
className.setStyleSheet("font: 14pt Comic Sans MS")
self.nameBox = QLineEdit(self)
self.nameBox.resize(200, 20)
self.nameBox.setStyleSheet("background-color: white;")
add = QPushButton("Add Class", self)
add.setStyleSheet("background-color: white;")
add.clicked.connect()
def create(self):
name = self.nameBox.text()
path = "Folder/" + name + ".csv"
classRows = [["Student Key", "Prefix", "Forename", "Surname", "Tutor"]]
with open(path, 'w') as file:
write = csv.writer(newClass, delimiter=',')
write.writerows(classRows)
self.close()
Once the file is created in the QWidget, I would like the Main Window to update to show the file that has just been added as a button, as is done with the files already in Folder when the Main Window is first opened.
Anybody have any idea how to do this?
Welcome..
i have two form: Form1=>Window & form2 =>MainWindow
The problem occurs after pressing the exit button in the main window. Where it is supposed to return to the login window again.
form1 (Window for Login) code:
import sys
from PyQt5.QtWidgets import *
from form2 import *
class Window(QWidget):
right_uname = "admin"
right_pword = "password"
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.lbl_intro = QLabel('Welcome, please login')
self.lbl_enter_username = QLabel('Username:')
self.lbl_enter_password = QLabel('Password:')
self.txt_enter_username = QLineEdit()
self.txt_enter_password = QLineEdit()
self.cb_login = QCheckBox('Stay logged in?')
self.btn_login = QPushButton('Login')
self.grid = QGridLayout()
self.grid.setSpacing(5)
self.grid.addWidget(self.lbl_intro, 1, 1)
self.grid.addWidget(self.lbl_enter_username, 2, 0)
self.grid.addWidget(self.txt_enter_username, 2, 1)
self.grid.addWidget(self.lbl_enter_password, 3, 0)
self.grid.addWidget(self.txt_enter_password, 3, 1)
self.grid.addWidget(self.cb_login, 4, 1)
self.grid.addWidget(self.btn_login, 5, 1)
self.v_box = QVBoxLayout()
self.v_box.addStretch(0)
self.v_box.addLayout(self.grid)
self.v_box.addStretch(0)
self.h_box = QHBoxLayout()
self.h_box.addStretch(0)
self.h_box.addLayout(self.v_box)
self.h_box.addStretch(0)
self.setLayout(self.h_box)
self.btn_login.clicked.connect(lambda: self.btn_login_clk(self.txt_enter_username, self.txt_enter_password, self.cb_login.isChecked(), self.lbl_intro))
self.setWindowTitle('Login test')
self.show()
def btn_login_clk(self, username, password, cb, intro):
if username.text() == self.right_uname and password.text() == self.right_pword:
if cb:
intro.setText('Welcome,' + ' ' + self.right_uname + ' ' + 'cb ticked')
else:
self.mw = MainWindow()
self.hide()
self.mw.show()
else:
intro.setText('Wrong username or password')
self.clear_box()
def clear_box(self):
self.txt_enter_username.clear()
self.txt_enter_password.clear()
self.txt_enter_username.setFocus()
if __name__ == '__main__':
app = QApplication(sys.argv)
a_window = Window()
sys.exit(app.exec())
from2 (MainWindow) code:
from form1 import *
class MainWindow(Window):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.lbl_intro = QLabel('Main Window')
self.lbl_user_logged = QLabel('Welcome,' + ' ' + self.right_uname)
self.lbl_append = QLabel('Write something')
self.txt_write_box = QLineEdit()
self.btn_append = QPushButton('Append')
self.btn_logout = QPushButton('Logout')
layout = QVBoxLayout()
layout.addWidget(self.lbl_intro)
layout.addWidget(self.lbl_user_logged)
layout.addWidget(self.lbl_append)
layout.addWidget(self.txt_write_box)
layout.addWidget(self.btn_append)
layout.addWidget(self.btn_logout)
self.setLayout(layout)
self.setWindowTitle('Main')
self.btn_append.clicked.connect(self.append_clk)
self.btn_logout.clicked.connect(self.logout_action)
self.show()
def append_clk(self):
self.appendee = open('text.txt', 'a')
self.appendee.write('hry')
self.appendee.close()
def logout_action(self):
self.close()
a_window = Window(self)
a_window.show()
a_window.clear_box()
When running:
name 'Window' is not defined
It looks like some sort of circular import problem to me, but I cannot replicate it though. Which version of Python are you using?
Anyway, firstly I would try changing form1 so that that import is local right before using MainWindow, to see if that solves the problem. I.e. removing the from form2 import * line at the top of form1 and changing your btn_login_clk method to this:
def btn_login_clk(self, username, password, cb, intro):
if username.text() == self.right_uname and password.text() == self.right_pword:
if cb:
intro.setText('Welcome,' + ' ' + self.right_uname + ' ' + 'cb ticked')
else:
from form2 import MainWindow # local import
self.mw = MainWindow()
self.hide()
self.mw.show()
else:
intro.setText('Wrong username or password')
self.clear_box()
On a slightly unrelated topic, I see that, when closing your MainWindow (i.e. logging out), you create a Window with the parent set to the MainWindow which you just closed. This will probably caluse the new window to be killed even before it appears (in my case, nothing appears and python exits with code 1), so the self argument should probably be removed:
def logout_action(self):
self.close()
a_window = Window() # no 'self' argument
a_window.show()
a_window.clear_box()
So I'm trying to make a simple file downloader in Python 3.4.2 and PyQt5
QThreads seems to be the way but there's no tutorials online or examples that I could understand for PyQt5. All I could find was Qt5 Reference for C/C++ and bunch of PyQt4 tutorials that don't work for PyQt5 and Python 3
Here's the GUI screenshot: http://i.imgur.com/KGjqRRK.png
And here's my code:
#!usr/bin/env python3
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from string import Template
import urllib.request
import sys
class Form(QWidget):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
lblUrl= QLabel("File URL:")
self.txtURL = QLineEdit()
self.bttDL = QPushButton("&Download")
self.pbar = QProgressBar()
self.pbar.setMinimum(0)
buttonLayout1 = QVBoxLayout()
buttonLayout1.addWidget(lblUrl)
buttonLayout1.addWidget(self.txtURL)
buttonLayout1.addWidget(self.bttDL)
buttonLayout1.addWidget(self.pbar)
self.bttDL.clicked.connect(self.bttPush)
mainLayout = QGridLayout()
mainLayout.addLayout(buttonLayout1, 0, 1)
self.setLayout(mainLayout)
self.setWindowTitle("pySFD")
def bttPush(self):
# check if the download is already running or just disable the button
# while it's running
url = self.txtURL.text()
if url == "":
QMessageBox.information(self, "Empty URL",
"Please enter the URL of the file you want to download.")
return
else:
filename = str(QFileDialog.getSaveFileName(self, 'Choose the download location and file name', '.'))
filename = filename[:-6]
filename = filename.split("('",maxsplit=1)[1]
self.dlThread = downloaderThread()
self.dlThread.connect(dlThread.run)
self.dlThread.start()
self.dlThread.emit(url)
class downloaderThread(QThread):
def __init__(self):
QThread.__init__(self)
def __del__(self):
self.wait()
def run(self, dlLink):
while dlLink.length == 0:
QThread.sleep(1)
pass
def report(block_count, block_size, total_size):
if block_count == 0:
self.pbar.setValue(0)
if (block_count * block_size) == total_size:
QMessageBox.information(self,"Done!","Download finished!")
return
self.pbar.setValue(self.pbar.value() + block_size)
urllib.request.urlretrieve(dlLink, filename, reporthook=report)
self.terminate()
if __name__ == '__main__':
app = QApplication(sys.argv)
screen = Form()
screen.show()
sys.exit(app.exec_())
I've tried a lot of ways and it just doesn't seem to work.
How do I make the progress bar (self.pbar) show the download progress in real time?
PS. This downloader is on my GitHub: https://github.com/dKatara/pySFD
Fixed it, it's not done yet, but threading works great!
Most recent version is on my GitHub here: https://github.com/dKatara/pySFD
#!usr/bin/env python3
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import urllib.request
import sys
import threading
dlThread = 0
hWindow = 0
fProgressCounter = 0.0
class Form(QWidget):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
global hWindow
hWindow = self
lblUrl = QLabel("File URL:")
self.txtURL = QLineEdit()
self.bttDL = QPushButton("&Download")
self.pbar = QProgressBar()
self.pbar.setMinimum(0)
self.pbar.setMaximum(100)
buttonLayout1 = QVBoxLayout()
buttonLayout1.addWidget(lblUrl)
buttonLayout1.addWidget(self.txtURL)
buttonLayout1.addWidget(self.bttDL)
buttonLayout1.addWidget(self.pbar)
self.bttDL.clicked.connect(self.bttPush)
mainLayout = QGridLayout()
mainLayout.addLayout(buttonLayout1, 0, 1)
self.setLayout(mainLayout)
self.setWindowTitle("pySFD")
def bttPush(self):
global dlThread
hSignals = sigHandling()
hSignals.dlProgress_update.connect(hSignals.pbar_incrementer)
hSignals.dlProgress_done.connect(hSignals.dlDone)
url = self.txtURL.text()
if url == "":
QMessageBox.information(self, "Empty URL",
"Please enter the URL of the file you want to download.")
return
else:
filename = str(QFileDialog.getSaveFileName(self, 'Choose the download location and file name', '.')) ## DETECT A CANCEL
filename = filename[:-6]
filename = filename.split("('",maxsplit=1)[1]
self.bttDL.setEnabled(False)
dlThread = threading.Thread(target=hSignals.runDL,args=(url, filename))
dlThread.start()
return
def pbarIncValue(self, val):
global fProgressCounter
#print("pbarIncValue({0})\nfProgressCounter={1}".format(val,fProgressCounter))
if self.pbar.value() >= 100:
self.dlProgress_done.emit()
return
if fProgressCounter > 1.0: # FIX
self.pbar.setValue(self.pbar.value() + 1)
fProgressCounter -= 1.0
fProgressCounter += val
else:
fProgressCounter += val
class sigHandling(QObject):
dlProgress_update = pyqtSignal(float)
dlProgress_done = pyqtSignal()
#pyqtSlot(float)
def pbar_incrementer(self, val):
hWindow.pbarIncValue(val)
#pyqtSlot()
def dlDone(self):
print("in dlDone")
hWindow.pbar.setValue(100)
hWindow.bttDL.setEnabled(True)
def runDL(self, dlLink, filename):
#print("in run")
global dlThread, hWindow
def report(block_count, block_size, total_size):
if block_count == 0:
#print("block_count == 0")
self.dlProgress_update.emit(0)
if (block_count * block_size) == total_size:
self.dlProgress_done.emit()
incAmount = float((100*block_size) / total_size)
#print("BS={0} TS={1} incAmount={2}".format(block_size,total_size,incAmount))
self.dlProgress_update.emit(incAmount)
urllib.request.urlretrieve(dlLink, filename, reporthook=report)
#print("emit dlProgress_done")
self.dlProgress_done.emit()
#print("about to leave dlThread")
pass
if __name__ == '__main__':
app = QApplication(sys.argv)
screen = Form()
screen.show()
sys.exit(app.exec_())