Set scroll area initially moved - python-3.x

I need to create a big widget inside a scroll area and initially set both sliders in the middle of the bar. The scroll bar does not work, the widgets are not well connected I think.
MRE:
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget
import sys
class Diedrico(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
# Draws stuff
class UiVentana(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(UiVentana, self).__init__(parent)
ventana.resize(1500, 1015)
ventana.setFixedSize(1500, 1015)
self.widget_central = QtWidgets.QWidget(ventana)
scrol = QtWidgets.QScrollArea(self.widget_central)
scrol.setWidgetResizable(True)
scrol.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scrol.setGeometry(QtCore.QRect(1010, 510, 470, 460))
self.Diedrico = Diedrico(scrol)
self.Diedrico.setGeometry(QtCore.QRect(0, 0, 1000, 1000))
# This widget should be big enough to use the scroll bar, but it does not work
ventana.setCentralWidget(self.widget_central)
ventana.show()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
ventana = QtWidgets.QMainWindow()
ui = UiVentana()
sys.exit(app.exec_())

It seems that the problem comes from scrol.setWidgetResizable(True), which seems to resize the content... setting this to False worked for me.
Also, to center the scrollbar, there are a few options, like setting the value of the verticalScrollBar or using ensureVisible(x, y).
A working solution:
from PyQt5 import QtCore, QtWidgets
import sys
class UiVentana(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(UiVentana, self).__init__(parent)
self.setupUi()
self.label.setGeometry(QtCore.QRect(10, 0, 282, 331))
self.label.setText("this is a long text\n" * 100)
self.scrollArea.verticalScrollBar().setValue(300)
def setupUi(self):
self.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(self)
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
self.scrollArea.setGeometry(QtCore.QRect(470, 330, 301, 211))
self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
self.scrollArea.setWidgetResizable(False)
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 282, 10000))
self.label = QtWidgets.QLabel(self.scrollAreaWidgetContents)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.setCentralWidget(self.centralwidget)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
ui = UiVentana()
ui.show()
sys.exit(app.exec_())

Related

How to use QtWebEngine createWindow in PyQt5

I am trying to make a window that contains a QWebEngineView. Now I want the browser to be able to handle the create window or _blank type triggers, or specifically to open a URL in a new window when required. In the below code, when there is requirement to create a window by the browser, createwindow() is called, but that doesn't open the window. Please help me with the correct way to open a new window by the browser when required in the below case.
import json
import sys
import os
import time
import json
import sys
import platform
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from PyQt5.QtWebEngineWidgets import QWebEngineSettings as QWebSettings
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtCore import QUrl
from main_dash import Ui_MainWindow
class MainDashWindow(QMainWindow):
socketSignal = QtCore.pyqtSignal(object) # must be defined in class level
def __init__(self):
QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
# self.ui.setupUi(self)
# ui = Ui_MainWindow()
self.isMax = 0
self.ui.setupUi(self)
def re_setup(self):
self.page = WebEnginePage2()
self.page.Notifications = True
self.ui.full_content_container.hide()
self.page.createWindow = True
self.page.settings().setAttribute(QWebSettings.JavascriptEnabled, True)
self.page.settings().setAttribute(QWebSettings.JavascriptCanOpenWindows, True)
self.page.settings().setAttribute(
QWebSettings.JavascriptCanAccessClipboard, True)
# self.full_content_container is the webengineview in the mainUi file
self.ui.full_content_container.setPage(self.page)
# self.ui.full_content_container.setContextMenuPolicy(Qt.NoContextMenu)
url6 = "...../icons_nec/ui/index.html"
self.ui.full_content_container.setUrl(QtCore.QUrl(url6))
self.ui.full_content_container.loadFinished.connect(
self.on_load_finished)
########################################################################
self.show()
## ==> END ##
def get_path(self, filename):
if hasattr(sys, "_MEIPASS"):
return f'{os.path.join(sys._MEIPASS, filename)}'
else:
return f'{filename}'
def on_load_finished(self):
self.ui.full_content_container.show()
class WebEnginePage2(QWebEnginePage):
def __init__(self, *args, **kwargs):
QWebEnginePage.__init__(self, *args, **kwargs)
self.featurePermissionRequested.connect(
self.onFeaturePermissionRequested)
def onFeaturePermissionRequested(self, url, feature):
self.setFeaturePermission(
url, feature, QWebEnginePage.PermissionGrantedByUser)
def createWindow(self,
wintype: QWebEnginePage.WebWindowType) -> QWebEngineView:
"""Called by Qt when a page wants to create a new tab or window.
In case the user wants to open a resource in a new tab, we use the
createWindow handling of the main page to achieve that.
See WebEngineView.createWindow for details.
"""
return self.page().inspectedPage().view().createWindow(wintype)
# Store external windows.
external_windows = []
def acceptNavigationRequest(self, url, _type, isMainFrame):
print("in navigation")
if _type == QWebEnginePage.NavigationTypeLinkClicked:
w = QWebEngineView()
w.setUrl(url)
w.show()
print("link detected")
# Keep reference to external window, so it isn't cleared up.
self.external_windows.append(w)
return False
# QDesktopServices.openUrl(url)
# elif _type == QWebEnginePage.NavigationType
return super().acceptNavigationRequest(url, _type, isMainFrame)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainDashWindow()
window.re_setup()
sys.exit(app.exec_())
Here is the Ui_MainWindow file, which is being imported above.
I need to figure out with such a scenario how can I implement createWindow() if required by websites.
from PyQt5 import QtWebEngineWidgets
import all_icons_rc
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1280, 720)
MainWindow.setMinimumSize(QtCore.QSize(1280, 720))
MainWindow.setMaximumSize(QtCore.QSize(1920, 1080))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_2.setSpacing(0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.Header = QtWidgets.QFrame(self.centralwidget)
self.Header.setMinimumSize(QtCore.QSize(0, 40))
self.Header.setMaximumSize(QtCore.QSize(16777215, 50))
self.Header.setStyleSheet("background-color: rgb(33, 37, 41);")
self.Header.setFrameShape(QtWidgets.QFrame.NoFrame)
self.Header.setFrameShadow(QtWidgets.QFrame.Raised)
self.Header.setObjectName("Header")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.Header)
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_4.setSpacing(0)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.frame_2 = QtWidgets.QFrame(self.Header)
self.frame_2.setStyleSheet("")
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
self.horizontalLayout_4.addWidget(self.frame_2)
self.frame = QtWidgets.QFrame(self.Header)
self.frame.setMaximumSize(QtCore.QSize(150, 16777215))
self.frame.setStyleSheet("/*background-color: rgb(85, 255, 0);*/")
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout.setSpacing(15)
self.horizontalLayout.setObjectName("horizontalLayout")
self.minimize_btn = QtWidgets.QPushButton(self.frame)
self.minimize_btn.setText("")
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(
":/icons/Icons/icons8_macos_minimize_50px.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.minimize_btn.setIcon(icon)
self.minimize_btn.setIconSize(QtCore.QSize(30, 30))
self.minimize_btn.setFlat(True)
self.minimize_btn.setObjectName("minimize_btn")
self.horizontalLayout.addWidget(self.minimize_btn)
self.maximize_btn = QtWidgets.QPushButton(self.frame)
self.maximize_btn.setText("")
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap(
":/icons/Icons/icons8_maximize_window_50px.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.maximize_btn.setIcon(icon1)
self.maximize_btn.setIconSize(QtCore.QSize(30, 30))
self.maximize_btn.setFlat(True)
self.maximize_btn.setObjectName("maximize_btn")
self.horizontalLayout.addWidget(self.maximize_btn)
self.close_btn = QtWidgets.QPushButton(self.frame)
self.close_btn.setText("")
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap(
":/icons/Icons/icons8_Close_50px_2.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.close_btn.setIcon(icon2)
self.close_btn.setIconSize(QtCore.QSize(30, 30))
self.close_btn.setFlat(True)
self.close_btn.setObjectName("close_btn")
self.horizontalLayout.addWidget(self.close_btn)
self.horizontalLayout_4.addWidget(self.frame)
self.verticalLayout_2.addWidget(self.Header)
self.body = QtWidgets.QFrame(self.centralwidget)
self.body.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.body.setFrameShadow(QtWidgets.QFrame.Raised)
self.body.setLineWidth(0)
self.body.setObjectName("body")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.body)
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.full_content_container = QtWebEngineWidgets.QWebEngineView(
self.body)#<----This is webengineview
self.full_content_container.setStyleSheet("background-color: rgb(85, 255, 255);\n"
"border:none;")
self.full_content_container.setObjectName("full_content_container")
self.verticalLayout_3.addWidget(self.full_content_container)
self.verticalLayout_2.addWidget(self.body)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
For now, just Ignore the icons.
index.html file snippet which is being loaded in webengineview for testing
<!DOCTYPE html>
<html>
<body>
<h1>The a target attribute</h1>
<p>Open link in a new window or tab: Visit PathOr!</p>
</body>
</html>
UPDATE:
Below is an implementaion based on your example code. Everything should work as expected if you completely replace your WebEnginePage2 class with this one:
class WebEnginePage2(QWebEnginePage):
_windows = {}
#classmethod
def newWindow(cls):
window = QWebEngineView()
window.setObjectName(f'window-{id(window)}')
window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
window.destroyed.connect(
lambda window: cls._windows.pop(window.objectName(), None))
window.setPage(cls(window))
cls._windows[window.objectName()] = window
return window
def __init__(self, *args, **kwargs):
QWebEnginePage.__init__(self, *args, **kwargs)
self.featurePermissionRequested.connect(
self.onFeaturePermissionRequested)
self.geometryChangeRequested.connect(self.handleGeometryChange)
def handleGeometryChange(self, rect):
view = self.view()
window = QtGui.QWindow.fromWinId(view.winId())
if window is not None:
rect = rect.marginsRemoved(window.frameMargins())
view.resize(rect.size())
view.show()
def createWindow(self, mode):
window = self.newWindow()
if mode != QtWebEngineWidgets.QWebEnginePage.WebDialog:
window.resize(800, 600)
window.show()
return window.page()
def onFeaturePermissionRequested(self, url, feature):
self.setFeaturePermission(
url, feature, QWebEnginePage.PermissionGrantedByUser)
You need to create a new instance of the browser window and keep a reference to it in a window list. It's also important to ensure the window is given an appropriate size, otherwise it won't be visible. For windows opened with javascript, the geometryChangeRequested signal can be used to set the requested size, otherwise a default should be used.
Below is a simple demo that implements the basic features. Hopefully it should be obvious how to adapt this to your own application:
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class Browser(QtWebEngineWidgets.QWebEngineView):
_windows = set()
#classmethod
def _removeWindow(cls, window):
cls._windows.discard(window)
#classmethod
def newWindow(cls):
window = cls()
cls._windows.add(window)
return window
def __init__(self, parent=None):
super().__init__(parent)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
self.page().geometryChangeRequested.connect(self.handleGeometryChange)
self.page().titleChanged.connect(self.setWindowTitle)
def closeEvent(self, event):
self._removeWindow(self)
event.accept()
def handleGeometryChange(self, rect):
window = QtGui.QWindow.fromWinId(self.winId())
if window is not None:
rect = rect.marginsRemoved(window.frameMargins())
self.resize(rect.size())
self.setFocus()
self.show()
def createWindow(self, mode):
window = self.newWindow()
if mode != QtWebEngineWidgets.QWebEnginePage.WebDialog:
window.resize(800, 600)
window.show()
return window
html = """
<html><head><title>Test Page</title>
<script type="text/javascript"><!--
var count = 0
var url = 'https://www.google.com'
function newWindow() {
count += 1
window.open(url, 'Test' + count, 'width=640,height=480');
}
--></script>
</head>
<body>
<input type="button" value="New Window" onclick="newWindow()" />
<p>Blank</p>
</body>
</html>"""
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
browser = Browser()
browser.setHtml(html)
browser.setGeometry(600, 100, 400, 200)
browser.show()
sys.exit(app.exec_())

PySide2 v5.12 : Creating a FileDialog on a click of a button

I designed a basic UI in the QtDesigner. Now i am trying to pop a simple file dialog on click of a button, below given is my GUI Code :
from PySide2 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
.....
.....
self.input_Image_GraphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.input_Image_GraphicsView.setGeometry(QtCore.QRect(730, 110, 480, 320))
self.input_Image_GraphicsView.setObjectName("input_Image_GraphicsView")
......
self.output_Image_GraphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.output_Image_GraphicsView.setGeometry(QtCore.QRect(730, 480, 480, 320))
self.output_Image_GraphicsView.setObjectName("output_Image_GraphicsView")
......
self.file_Select_Btn = QtWidgets.QPushButton(self.centralwidget)
self.file_Select_Btn.setGeometry(QtCore.QRect(1082, 80, 121, 28))
self.file_Select_Btn.setObjectName("file_Select_Btn")
self.file_Select_Btn.clicked.connect(self.selectFile)
.....
.....
def selectFile():
self.path_To_File = QtWidgets.QFileDialog.getOpenFileName(self, QtCore.QObject.tr("Load Image"), QtCore.QObject.tr("~/Desktop/"), QtCore.QObject.tr("Images (*.jpg)"))
print(self.path_To_File)
.....
.....
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
This is the error that i get :
TypeError: descriptor 'tr' requires a 'PySide2.QtCore.QObject' object but received a 'str'
When i wasnt using the 'tr', I was getting :
TypeError: 'PySide2.QtWidgets.QFileDialog.getOpenFileName' called with wrong
argument types:
PySide2.QtWidgets.QFileDialog.getOpenFileName(Ui_MainWindow, str, str, str)
Supported signatures:
PySide2.QtWidgets.QFileDialog.getOpenFileName(PySide2.QtWidgets.QWidget = None, str = '', str = '', str = '', str = '', PySide2.QtWidgets.QFileDialog.Options = Default(QFileDialog.Options))
I have read the python documentation for Qt ver 5.12 given here : https://doc.qt.io/qtforpython/PySide2/QtWidgets/QFileDialog.html
That didnt help either. Where did i go wrong??
Basically i want to :
Get a FileDialog -> Select an JPG File
Get the path of the file in python code -> Populate a GraphicsView with the image on the GUI
I am currently struggling with both the aspects
Any help will be appreciated..
You should not mix your program logic with the generated UI files, instead, create a QMainWindow class wrapper and inherit from both QMainWindow and the UI class.
As per your actual problem, you were just missing a reference to an object (for example, self) before passing the text to translate, I added a small helper method to handle that in the following example:
import sys
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import QObject, QRectF, Qt
from PySide2.QtWidgets import QMainWindow, QFileDialog, QWidget, QVBoxLayout, QGraphicsScene, QGraphicsView
from PySide2.QtGui import QPixmap
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.gridLayout = QtWidgets.QGridLayout(self.centralWidget)
self.file_Select_Btn = QtWidgets.QPushButton(self.centralWidget)
self.file_Select_Btn.setGeometry(QtCore.QRect(1082, 80, 121, 28))
self.file_Select_Btn.setObjectName("file_Select_Btn")
self.file_Select_Btn.setText("Load Image")
self.gridLayout.addWidget(self.file_Select_Btn)
MainWindow.setCentralWidget(self.centralWidget)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self):
Ui_MainWindow.__init__(self)
QMainWindow.__init__(self)
# Initialize UI
self.setupUi(self)
self.file_Select_Btn.clicked.connect(self.showImage)
def tr(self, text):
return QObject.tr(self, text)
def showImage(self):
path_to_file, _ = QFileDialog.getOpenFileName(self, self.tr("Load Image"), self.tr("~/Desktop/"), self.tr("Images (*.jpg)"))
self.image_viewer = ImageViewer(path_to_file)
self.image_viewer.show()
class ImageViewer(QWidget):
def __init__(self, image_path):
super().__init__()
self.scene = QGraphicsScene()
self.view = QGraphicsView(self.scene)
layout = QVBoxLayout()
layout.addWidget(self.view)
self.setLayout(layout)
self.load_image(image_path)
def load_image(self, image_path):
pixmap = QPixmap(image_path)
self.scene.addPixmap(pixmap)
self.view.fitInView(QRectF(0, 0, pixmap.width(), pixmap.height()), Qt.KeepAspectRatio)
self.scene.update()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())

How to send a signal from a QDialog to a QMainWindow class

I have made a UI which includes a mainwindow and a button that opens a dialog window. I want to send the current text changed signal from a line edit in the dialog window to the Mainwindow class as a variable. An example of the code I am making is below:
from PyQt5 import QtCore, QtGui, QtWidgets
from selenium import webdriver
import time
import threading
from bs4 import BeautifulSoup as soup
import requests
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(388, 179)
self.lineEdit_2 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_2.setGeometry(QtCore.QRect(100, 100, 271, 21))
font = QtGui.QFont()
font.setFamily("Yu Gothic")
self.lineEdit_2.setFont(font)
self.lineEdit_2.setStyleSheet("background-color: transparent;\n"
"color: rgb(255, 255, 255);")
self.lineEdit_2.setObjectName("lineEdit_2")
class Dialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
QtWidgets.QDialog.__init__(self, parent)
self.setupUi(self)
# self.pushButton.pressed.connect(self.textEdit.clear)
# self.pushButton.pressed.connect(self.sejd)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.keyworddict = {}
self.count = {}
MainWindow.setObjectName("MainWindow")
MainWindow.resize(803, 538)
MainWindow.setMinimumSize(QtCore.QSize(0, 0))
MainWindow.setMaximumSize(QtCore.QSize(10000, 10000))
self.centralWidget = QtWidgets.QWidget(MainWindow)
self.centralWidget.setObjectName("centralWidget")
self.pushButton = QtWidgets.QPushButton(self.centralWidget)
self.pushButton.setGeometry(QtCore.QRect(180, 210, 75, 23))
font = QtGui.QFont()
font.setFamily("Yu Gothic")
font.setBold(True)
font.setWeight(75)
self.pushButton.setFont(font)
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralWidget)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.pushButton.pressed.connect(self.on_Button_clicked)
def on_Button_clicked(self):
dialog = QtWidgets.QDialog()
dialog.ui = Ui_Dialog()
dialog.ui.setupUi(dialog)
dialog.setWindowTitle("Login")
dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
dialog.exec_()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.setWindowTitle("ui")
w.show()
sys.exit(app.exec_())
All help appreciated. I would preferably like an example using the code above.
There are at least two simple ways to do this. You can either connect a signal when the dialog is created, or just retrieve the text after the dialog closes:
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
...
def dialogTextChanged(self, text):
print(text)
def on_Button_clicked(self):
dialog = QtWidgets.QDialog()
dialog.ui = Ui_Dialog()
dialog.ui.setupUi(dialog)
# connect signal to slot
dialog.ui.lineEdit_2.textChanged.connect(self.dialogTextChanged)
dialog.setWindowTitle("Login")
# this is not needed
# dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
dialog.exec_()
# or retrieve text after dialog closes
print(dialog.ui.lineEdit_2.text())
dialog.deleteLater()
If this is a login dialog, you should probably have an accept button which is connected to the dialog's accept() slot. Then you can check the exit status of the dialog like this:
if dialog.exec_() == QtWidgets.QDialog.Accepted:
text = dialog.ui.lineEdit_2.text()
# do sothing with text ...
dialog.deleteLater()

Show sub window in main window

Can't work out how to embed a window in a main window using classes:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
Qt4 tutorial using classes
This example will be built
on over time.
"""
import sys
from PyQt4 import QtGui, QtCore
class Form(QtGui.QWidget):
def __init__(self, MainWindow):
super(Form, self).__init__()
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__()
self.setGeometry(50, 50, 1600, 900)
new_window = Form(self)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
main_window = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
This is supposed to be the single most basic bit of code using classes. How do I get the second window to show please.
As ekhumoro already pointed out, your widget needs to be a child of your mainWindow. However, I do not think that you need to call show for the widget, since it anyways gets called as soon as its parent (MainWindow) calls show. As mata pointed out correctly, the proper way to add a Widget to a MainWindow instance is to use setCentralWidget. Here is a working example for clarification:
import sys
from PyQt4 import QtGui, QtCore
class Form(QtGui.QWidget):
def __init__(self, parent):
super(Form, self).__init__(parent)
self.lbl = QtGui.QLabel("Test", self)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__()
self.setGeometry(50, 50, 1600, 900)
new_window = Form(self)
self.setCentralWidget(new_window)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
main_window = MainWindow()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Python 3.5, pyqt5 progress bar gui in seperate window

I am new to PyQt5 and pretty new to Python. I am trying to create a graphical user interface using PyQt5 in Python 3.5, where I click a button to launch a separate window in which the progress bar iterates up to 100 and then closing the window at the end of iteration to generate a message "it worked".
The problem is the progress bar is created but doesn't update and after reaching the end it doesn't display the message that it worked. When I try to debug it crashes completely with no warning as to why. I don't know how else to debug the code
My progress bar code is shown below:
from PyQt5 import QtCore, QtWidgets
import sys
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(1075, 84)
self.progressBar = QtWidgets.QProgressBar(Form)
self.progressBar.setGeometry(QtCore.QRect(30, 30, 1000, 35))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.progressBar.sizePolicy().hasHeightForWidth())
self.progressBar.setSizePolicy(sizePolicy)
self.progressBar.setMinimumSize(QtCore.QSize(1000, 35))
self.progressBar.setMaximumSize(QtCore.QSize(1000, 35))
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def setValue(self, val):
self.progressBar.setProperty("value", val)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Progress bar"))
The main program is given below
from PyQt5.QtWidgets import QApplication, QDialog, QWidget, QPushButton, QMessageBox
import ProgressBar
import sys
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 button - pythonspot.com'
self.left = 200
self.top = 200
self.width = 320
self.height = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
button = QPushButton('PyQt5 button', self)
button.setToolTip('This is an example button')
button.move(100, 70)
button.clicked.connect(self.on_click)
self.show()
def on_click(self):
print('PyQt5 button click')
app1 = QApplication(sys.argv)
window = QDialog()
ui = ProgressBar.Ui_Form()
ui.setupUi(window)
window.show()
for i in range(0, 100):
ui.setValue(((i + 1) / 100) * 100)
app1.quit()
QMessageBox.information(self, "Message", "Data Loaded")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Any help would be greatly appreciated.
Here is my final code. I have tried to include some good practices with using pyqt designer and not editing the created file directly but run it from another file and call into it. This has made things much easier when I wanted to change things as suggested. I have also included a time.sleep(0.1) to the code to slow it down so you can see it working. Hope it helps.
ProgressBar_ui.py - file generated by converted in python from ProgressBar.ui
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'Base.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(1075, 84)
self.progressBar = QtWidgets.QProgressBar(Form)
self.progressBar.setGeometry(QtCore.QRect(30, 30, 1000, 35))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.progressBar.sizePolicy().hasHeightForWidth())
self.progressBar.setSizePolicy(sizePolicy)
self.progressBar.setMinimumSize(QtCore.QSize(1000, 35))
self.progressBar.setMaximumSize(QtCore.QSize(1000, 35))
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Progress bar"))
ProgressBar.py - Calls ProgrssBar.ui
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from ProgressBar_ui import Ui_Form
class ProgressBar(QtWidgets.QDialog, Ui_Form):
def __init__(self, desc = None, parent=None):
super(ProgressBar, self).__init__(parent)
self.setupUi(self)
self.show()
if desc != None:
self.setDescription(desc)
def setValue(self, val): # Sets value
self.progressBar.setProperty("value", val)
def setDescription(self, desc): # Sets Pbar window title
self.setWindowTitle(desc)
def main():
app = QtWidgets.QApplication(sys.argv) # A new instance of QApplication
form = ProgressBar('pbar') # We set the form to be our MainWindow (design)
app.exec_() # and execute the app
if __name__ == '__main__': # if we're running file directly and not importing it
main() # run the main function
Main_program.py - Run from here
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox
from ProgressBar import ProgressBar
import sys, time
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'PyQt5 button - pythonspot.com'
self.left = 200
self.top = 200
self.width = 320
self.height = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
button = QPushButton('PyQt5 button', self)
button.setToolTip('This is an example button')
button.move(100, 70)
button.clicked.connect(self.on_click)
self.show()
def on_click(self):
pb = ProgressBar()
for i in range(0, 100):
time.sleep(0.05)
pb.setValue(((i + 1) / 100) * 100)
QApplication.processEvents()
pb.close()
QMessageBox.information(self, "Message", "Data Loaded")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Figured out solution eventually. 3 problems:
1) Should only call QApplication once in the main application an not again
2) Add QApplication.processEvents() to the forloop so it updates the progressbar continuously
3) Add window.close() after the forloop so it closes

Resources