How to integrate youtube-dl in PyQt5 - python

I'm trying to show the live progress of download in the gui. I'm getting the live progress of download in cmd but gui only updates when the download is complete.
def myhook(self,d):
self.percentage=QLabel(self)
self.d=d
if self.d['status']=='finished':
print("finished")
if self.d['status']=='downloading':
print(self.d['filename'],self.d['total_bytes'],self.d['downloaded_bytes'],self.d['elapsed'],self.d['eta']
,str(str(self.d['speed']/1000)[0:5]+'KiB/s')
,str((self.d['downloaded_bytes']*100)/self.d['total_bytes'])[0:5]+'%')
if self.d['total_bytes']>1048576:
total_size=self.d['total_bytes']/1048576
total_size=str(total_size)[0:5]+' MB'
if self.d['total_bytes']>1073741824:
total_size=self.d['total_bytes']/1073741824
total_size=str(total_size)[0:5]+' GB'
self.percentage.setText('{} {}'.format(total_size
,str((self.d['downloaded_bytes']*100)/self.d['total_bytes'])[0:5]+' %'))
self.percentage.setStyleSheet('color:white;border-bottom:2px solid orange;')
self.percentage.setFont(QFont('Arial',15))
self.percentage.resize(500,30)
self.percentage.move(320,650)
self.percentage.show()
self.url=self.urlfield.text()
print("144p")
options={'format':'bestvideo[height=144]+bestaudio/best','noplaylist':True,'postprocessors':[{'key':'FFmpegMetadata'}]
,'noprogress':True,'progress_hooks':[self.myhook]}
with youtube_dl.YoutubeDL(options) as ydll:
ydll.download(['{}'.format(self.url)])

Since many times you have wondered about how is the correct way to obtain information from youtube-dl and show it in a GUI written with pyqt5, I will take the license to go beyond the current question and show a more generic example.
The youtube_dl download method is very time consuming so it should not be executed in the main thread as it generates unwanted effects such as window freezing. On the other hand, there are 2 means of information provided by youtube_dl: the hooks and the logger. And these media are executed in the same thread as the download method, so they should not be accessed directly but through signals.
qyoutubedl.py
import threading
from PyQt5 import QtCore
import youtube_dl
class QLogger(QtCore.QObject):
messageChanged = QtCore.pyqtSignal(str)
def debug(self, msg):
self.messageChanged.emit(msg)
def warning(self, msg):
self.messageChanged.emit(msg)
def error(self, msg):
self.messageChanged.emit(msg)
class QHook(QtCore.QObject):
infoChanged = QtCore.pyqtSignal(dict)
def __call__(self, d):
self.infoChanged.emit(d.copy())
class QYoutubeDL(QtCore.QObject):
def download(self, urls, options):
threading.Thread(
target=self._execute, args=(urls, options), daemon=True
).start()
def _execute(self, urls, options):
with youtube_dl.YoutubeDL(options) as ydl:
ydl.download(urls)
for hook in options.get("progress_hooks", []):
if isinstance(hook, QHook):
hook.deleteLater()
logger = options.get("logger")
if isinstance(logger, QLogger):
logger.deleteLater()
main.py
from PyQt5 import QtWidgets
from qyoutubedl import QLogger, QHook, QYoutubeDL
from hurry.filesize import size
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.url_le = QtWidgets.QLineEdit()
self.download_btn = QtWidgets.QPushButton(self.tr("Download"))
self.progress_lbl = QtWidgets.QLabel()
self.download_pgb = QtWidgets.QProgressBar()
self.log_edit = QtWidgets.QPlainTextEdit(readOnly=True)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QGridLayout(central_widget)
lay.addWidget(QtWidgets.QLabel(self.tr("url:")))
lay.addWidget(self.url_le, 0, 1)
lay.addWidget(self.download_btn, 0, 2)
lay.addWidget(self.progress_lbl, 1, 1, 1, 2)
lay.addWidget(self.download_pgb, 2, 1, 1, 2)
lay.addWidget(self.log_edit, 3, 1, 1, 2)
self.progress_lbl.hide()
self.downloader = QYoutubeDL()
self.download_btn.clicked.connect(self.download)
self.url_le.setText("https://www.youtube.com/watch?v=BaW_jenozKc")
self.resize(640, 480)
def download(self):
qhook = QHook()
qlogger = QLogger()
url = self.url_le.text()
options = {
"format": "bestvideo[height=144]+bestaudio/best",
"noplaylist": True,
"postprocessors": [{"key": "FFmpegMetadata"}],
"noprogress": True,
"logger": qlogger,
"progress_hooks": [qhook],
}
self.downloader.download([url], options)
qhook.infoChanged.connect(self.handle_info_changed)
qlogger.messageChanged.connect(self.log_edit.appendPlainText)
self.download_pgb.setRange(0, 1)
def handle_info_changed(self, d):
if d["status"] == "downloading":
self.progress_lbl.show()
total = d["total_bytes"]
downloaded = d["downloaded_bytes"]
self.progress_lbl.setText("{} of {}".format(size(downloaded), size(total)))
self.download_pgb.setMaximum(total)
self.download_pgb.setValue(downloaded)
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Related

How to Use the Android 'IP Webcam' App with Python

working on simple GUI project. I've got some code from online,and found out how to connect the IP-webcam app, but the question is how do I use this code in my PyQt4 GUI so that the visual of the camera will be shown in the scroll-area widget.
This is the code i used:
import urllib
import cv2
import numpy as np
url='http://192.168.0.100:8080/shot.jpg'
while True:
imgResp=urllib.urlopen(url)
imgNp=np.array(bytearray(imgResp.read()),dtype=np.uint8)
img=cv2.imdecode(imgNp,-1)
# all the opencv processing is done here
cv2.imshow('test',img)
if ord('q')==cv2.waitKey(10):
exit(0)
As #furas points out, a possible option is to use numpy and cv2 to convert it to QPixmap and display it in a QLabel, and so that it looks like streaming run it in a loop.
But instead of getting complicated with all of the above, the simplest thing is to use QtNetwork to get the bytes and convert it directly to QPixmap and send it through signals:
from PyQt4 import QtCore, QtGui, QtNetwork
class IPWebcam(QtCore.QObject):
pixmapChanged = QtCore.pyqtSignal(QtGui.QPixmap)
def __init__(self, url, parent=None):
super(IPWebcam, self).__init__(parent)
self._url = url
self.m_manager = QtNetwork.QNetworkAccessManager(self)
self.m_manager.finished.connect(self._on_finished)
self.m_stopped = True
def start(self):
self.m_stopped = False
self._launch_request()
def stop(self):
self.m_stopped = True
def _launch_request(self):
request = QtNetwork.QNetworkRequest(QtCore.QUrl(self._url))
self.m_manager.get(request)
#QtCore.pyqtSlot(QtNetwork.QNetworkReply)
def _on_finished(self, reply):
ba = reply.readAll()
pixmap = QtGui.QPixmap()
if pixmap.loadFromData(ba):
self.pixmapChanged.emit(pixmap)
if not self.m_stopped:
self._launch_request()
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.m_label = QtGui.QLabel()
self.m_button = QtGui.QPushButton(
"Start", clicked=self.onClicked, checkable=True
)
lay = QtGui.QVBoxLayout(self)
lay.addWidget(self.m_label)
lay.addWidget(self.m_button)
self.resize(640, 480)
url = "http://192.168.0.100:8080/shot.jpg"
self.m_webcam = IPWebcam(url, self)
self.m_webcam.pixmapChanged.connect(self.m_label.setPixmap)
#QtCore.pyqtSlot(bool)
def onClicked(self, checked):
if checked:
self.m_button.setText("Stop")
self.m_webcam.start()
else:
self.m_button.setText("Start")
self.m_webcam.stop()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())

How can I make a QWidget open after a QWidget closes?

I have the below code:
import os
from functools import partial
import numpy as np
from PyQt5 import QtCore, QtWidgets
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.resize(500, 500)
self.setWindowFlags(
self.windowFlags() | QtCore.Qt.MSWindowsFixedSizeDialogHint
)
self.setWindowTitle("nCode analysis set-up")
self.wait_window = WaitWindow()
thread = QtCore.QThread(self)
thread.start()
self.m_worker = Worker()
self.m_worker.moveToThread(thread)
self.m_worker.new_content_signal.connect(self.get_content)
# Creating the top level grid layout
mainGrid = QtWidgets.QGridLayout(self)
self.analysis_type_label = QtWidgets.QLabel(self)
self.analysis_type_label.setText("Type of analysis")
mainGrid.addWidget(self.analysis_type_label, 0, 0)
self.analysis_type_combo = QtWidgets.QComboBox(self)
self.analysis_type_combo.addItems(["Fatigue", "Proof plus fatigue"])
mainGrid.addWidget(self.analysis_type_combo, 0, 1, 1, 2)
self.load_deck_type_label = QtWidgets.QLabel(self)
self.load_deck_type_label.setText("Type of fatigue deck")
mainGrid.addWidget(self.load_deck_type_label, 1, 0)
self.load_deck_type_combo = QtWidgets.QComboBox(self)
self.load_deck_type_combo.addItems(
["Regen braking", "No regen braking"]
)
mainGrid.addWidget(self.load_deck_type_combo, 1, 1, 1, 2)
self.analysis_engine_type_label = QtWidgets.QLabel(self)
self.analysis_engine_type_label.setText("Analysis Engine")
mainGrid.addWidget(self.analysis_engine_type_label, 2, 0)
self.analysis_engine_type_combo = QtWidgets.QComboBox(self)
self.analysis_engine_type_combo.addItems(["EN analysis", "SN analysis"])
mainGrid.addWidget(self.analysis_engine_type_combo, 2, 1, 1, 2)
# Creating a scrolable area to accommodate for a large number of components with possible lenghty names
self.scrollArea = QtWidgets.QScrollArea(self)
# The line below is absolutely required to make the scrollable area work.
self.scrollArea.setWidgetResizable(True)
mainGrid.addWidget(self.scrollArea, 3, 0, 1, 3)
self.secondaryWidget = QtWidgets.QWidget()
self.scrollArea.setWidget(self.secondaryWidget)
self.secondaryGrid = QtWidgets.QGridLayout(self.secondaryWidget)
self.createDCL = QtWidgets.QPushButton(self)
self.createDCL.setText("Create DCL")
mainGrid.addWidget(self.createDCL, 4, 0, 1, 3)
def start_task(self):
if not os.path.exists("loading_database.db"):
QtWidgets.QMessageBox.information(
None,
"Loading database missing",
"Loading database has not been found. Creation of a new one will be attempted",
)
# self.loadingDatabaseCreator()
QtWidgets.QMessageBox.information(
None, "Successful", "Loading database succesfully created"
)
filePath, _ = QtWidgets.QFileDialog.getOpenFileName(
None, "Select input model", "", "Input deck (*.inp)", "*.inp"
)
if filePath:
self.wait_window.show()
self.m_worker.finished.connect(self.wait_window.close)
wrapper = partial(self.m_worker.read_file, filePath)
# Launch the task in a reasonable time for the window to show
QtCore.QTimer.singleShot(100, wrapper)
w.show()
self.wait_window.raise_()
self.wait_window.activateWindow()
#QtCore.pyqtSlot(int, str)
def get_content(self, i, content):
label = QtWidgets.QLabel("{} material".format(content))
linedit = QtWidgets.QLineEdit(placeholderText="Drop material name here")
linedit.setFixedWidth(150)
button = QtWidgets.QPushButton("Pick material")
self.secondaryGrid.addWidget(label, 2 + i, 0)
self.secondaryGrid.addWidget(linedit, 2 + i, 1)
self.secondaryGrid.addWidget(button, 2 + i, 2)
class WaitWindow(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("Info")
self.resize(600, 200)
layout = QtWidgets.QVBoxLayout(self)
self.message = QtWidgets.QLabel()
self.message.setFixedWidth(550)
self.message.setText("Please wait while input file is being read")
layout.addWidget(self.message)
class Worker(QtCore.QObject):
finished = QtCore.pyqtSignal()
new_content_signal = QtCore.pyqtSignal(int, str)
#QtCore.pyqtSlot(str)
def read_file(self, fileName):
i = 0
collector_array = []
with open(fileName, "r") as model_file_obj:
for line in model_file_obj.readlines():
if "*ELEMENT," in line and "DCOUP3D" not in line:
t = line.split("ELSET=")[1][:-1]
if t not in collector_array:
self.new_content_signal.emit(i, t)
QtCore.QThread.msleep(10)
collector_array.append(t)
i += 1
self.finished.emit()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWidget()
w.start_task()
sys.exit(app.exec_())
It looks like a lot of code but the MainWidget is initialized first. After the initialization the MainWidget function of start_task is called which show's the WaitWindow QDialog, asks the user for the input file which it starts parsing and then shows the MainWidget QWidget window. While this is not too bad I would like the user to not see the MainWidget window until the file has finished parsing and the WaitWindow is closed. Any ideas?
I do not understand why you use w.show(), remove it.
Going to the problem, if you want the MainWidget to show after executing the task, you just have to connect the show method to the finished signal
# ...
self.m_worker.finished.connect(self.wait_window.close)
self.m_worker.finished.connect(self.show)
# ...

pyqt5 autocomplete QLineEdit - Google places autocomplete

I am trying to create something like this (autocomplete places) in pyqt5 QLineEdit.
There is a class called QCompleter with which i can suggest the content, but it requires an already formed list, but this google places api is a suggestion based function, how can i send each keystroke to google api and get the suggestion back and load in Qtextedit, is there a better way to do it
For this case you can create a custom model that makes a request using Place Autocomplete, and set that model to a QCompleter:
import json
from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork
API_KEY = "<API_KEY>"
class SuggestionPlaceModel(QtGui.QStandardItemModel):
finished = QtCore.pyqtSignal()
error = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(SuggestionPlaceModel, self).__init__(parent)
self._manager = QtNetwork.QNetworkAccessManager(self)
self._reply = None
#QtCore.pyqtSlot(str)
def search(self, text):
self.clear()
if self._reply is not None:
self._reply.abort()
if text:
r = self.create_request(text)
self._reply = self._manager.get(r)
self._reply.finished.connect(self.on_finished)
loop = QtCore.QEventLoop()
self.finished.connect(loop.quit)
loop.exec_()
def create_request(self, text):
url = QtCore.QUrl("https://maps.googleapis.com/maps/api/place/autocomplete/json")
query = QtCore.QUrlQuery()
query.addQueryItem("key", API_KEY)
query.addQueryItem("input", text)
query.addQueryItem("types", "geocode")
query.addQueryItem("language", "en")
url.setQuery(query)
request = QtNetwork.QNetworkRequest(url)
return request
#QtCore.pyqtSlot()
def on_finished(self):
reply = self.sender()
if reply.error() == QtNetwork.QNetworkReply.NoError:
data = json.loads(reply.readAll().data())
if data['status'] == 'OK':
for prediction in data['predictions']:
self.appendRow(QtGui.QStandardItem(prediction['description']))
self.error.emit(data['status'])
self.finished.emit()
reply.deleteLater()
self._reply = None
class Completer(QtWidgets.QCompleter):
def splitPath(self, path):
self.model().search(path)
return super(Completer, self).splitPath(path)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._model = SuggestionPlaceModel(self)
completer = Completer(self, caseSensitivity=QtCore.Qt.CaseInsensitive)
completer.setModel(self._model)
lineedit = QtWidgets.QLineEdit()
lineedit.setCompleter(completer)
label = QtWidgets.QLabel()
self._model.error.connect(label.setText)
lay = QtWidgets.QFormLayout(self)
lay.addRow("Location: ", lineedit)
lay.addRow("Error: ", label)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.resize(400, w.sizeHint().height())
w.show()
sys.exit(app.exec_())
I faced the same issue, at first I tried #eyllanasec's answer. But for some reason, the performance is not so good (often stuck or hang) in the platform that I use (I was creating a plugin for Qt-based software using PyQt). It is running fine independently though, so perhaps it's specific to my platform.
In the end, I found a Qt example project for a similar case, Google Suggest. You can find it https://doc.qt.io/qt-5/qtnetwork-googlesuggest-example.html. It creates a custom class to handle the search and the pop-up window (using QTreeWidget).
Since the example is in Qt, I port it to PyQt with small modification https://github.com/ismailsunni/scripts/blob/master/autocomplete_from_url.py

how i can make thread for progress bar with pafy

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_())

Using the QWizard next slot in pyside

I've created a wizard with Pyside.
On one page, I create a new thread, which starts an installer.
When the installer is ready, the Wizard should go forward automatically, without clicking the next button.
I've read the pyside documentation, and now my understanding is, that QWizard has a next function. But how can I use this function?
My test is working fine:
from PySide.QtGui import *
from PySide.QtCore import *
...
...
class Install(QWizardPage):
def __init__(self, parent=None):
super(Install, self).__init__(parent)
def initializePage(self):
self.setTitle("Install")
label = QLabel("Install")
label.setWordWrap(True)
layout = QVBoxLayout()
self.progressBar = QProgressBar(self)
self.progressBar.setRange(0,1)
self.progressBar.setRange(0,0)
layout.addWidget(self.progressBar)
layout.addWidget(label)
self.setLayout(layout)
self.myTask = TaskThread()
self.myTask.start()
self.myTask.taskFinished.connect(self.Finished)
def Finished(self):
print("finish")
def isComplete(self):
return False
class TaskThread(QThread):
taskFinished = Signal()
def run(self):
a = 0
while a != 10000:
print("test")
a += 1
self.taskFinished.emit()
And when I try to use the next function I try:
self.CallNext = QWizard().next
self.myTask.taskFinished.connect(self.CallNext)
And also:
self.myTask.taskFinished.connect(QWizard().next)
But this is not working
This connection should be done in the context where the QWizard and QWizardPage exist, but before that we must move the creation of the QThread to the constructor, for example in the following example I do in the main:
class Install(QWizardPage):
def __init__(self, parent=None):
super(Install, self).__init__(parent)
self.myTask = TaskThread()
def initializePage(self):
[...]
self.setLayout(layout)
self.myTask.start()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
wizard = QWizard()
install = Install()
install.setTitle("installer")
install.myTask.taskFinished.connect(wizard.next)
wizard.addPage(install)
page = QWizardPage()
page.setTitle("next Page")
wizard.addPage(page)
wizard.show()
sys.exit(wizard.exec_())

Categories