PySide2 v5.12 : Creating a FileDialog on a click of a button - python-3.x

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

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

Python PyQt5 Terminal Command execution problem on a button click

I'm trying to create an application, that can execute an embedded Terminal command when ever the button is clicked. The actual problem occurs when i click the button and nothing happens.
I have two scripts one has a terminal widget and the other has the main GUI. Any Help, would be highly appreciated.
That's first Script
import sys
from PyQt5 import QtCore, QtWidgets
class EmbTerminal(QtWidgets.QWidget):
def __init__(self, parent=None):
super(EmbTerminal, self).__init__(parent)
self._process = []
self.start_process('urxvt',['-embed', str(int(self.winId())),"-e","tmux"])
def start_process(self,prog,options):
child = QtCore.QProcess(self)
self._process.append(child)
child.start(prog,options)
def run_command(self, command = "ls" ):
program = "tmux"
options = []
options.extend(["send-keys"])
options.extend([command])
options.extend(["Enter"])
self.start_process(program, options)
That's Second Script
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(745, 496)
self.tabWidget = QtWidgets.QTabWidget(Dialog)
self.tabWidget.setGeometry(QtCore.QRect(100, 190, 561, 261))
self.tabWidget.setObjectName("tabWidget")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.tabWidget.addTab(EmbTerminal(), "Terminal")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.tabWidget.addTab(self.tab_2, "")
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(280, 70, 211, 71))
self.pushButton.setObjectName("pushButton")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.pushButton.clicked.connect(lambda: EmbTerminal.run_command(EmbTerminal(), "ls"))
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Dialog", "Tab 1"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("Dialog", "Tab 2"))
self.pushButton.setText(_translate("Dialog", "ls"))
from terminal5 import EmbTerminal
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
You should consider the following:
You should not modify the code generated by Qt Designer (unless you understand its logic)
Do not implement the logic in the class generated by Qt Designer, it is advisable to create a new class that inherits from the appropriate widget and use the other class to fill it.
In your case the problem is that the EmbTerminal() object in lambda: EmbTerminal.run_command(EmbTerminal(), "ls") only exists while the lambda is running, but the lambda runs for a very short time causing the command not to be sent causing the error.
Considering the above, the solution is:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(745, 496)
self.tabWidget = QtWidgets.QTabWidget(Dialog)
self.tabWidget.setGeometry(QtCore.QRect(100, 190, 561, 261))
self.tabWidget.setObjectName("tabWidget")
self.pushButton = QtWidgets.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(280, 70, 211, 71))
self.pushButton.setObjectName("pushButton")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton.setText(_translate("Dialog", "ls"))
from terminal5 import EmbTerminal
class Dialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.terminal = EmbTerminal()
self.tabWidget.addTab(self.terminal, "Terminal")
self.pushButton.clicked.connect(self.on_clicked)
#QtCore.pyqtSlot()
def on_clicked(self):
self.terminal.run_command("ls")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
On the other hand if you are only going to send commands then it is not necessary to store the QProcess, instead use QProcess: startDetached and make run_command a classmethod:
class EmbTerminal(QtWidgets.QWidget):
# ...
#staticmethod
def run_command(command = "ls" ):
program = "tmux"
options = []
options.extend(["send-keys"])
options.extend([command])
options.extend(["Enter"])
QtCore.QProcess.startDetached(program, options)

Python: Access class method variable from another file

I have a PyQt5 GUI code and it has a Ui_MainWindow class and this class has a setupUI method. Here is my gui.py:
import io
import sys
import os
import core as c
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1022, 637)
MainWindow.setMinimumSize(QtCore.QSize(1022, 637))
MainWindow.setMaximumSize(QtCore.QSize(1022, 637))
font = QtGui.QFont()
font.setKerning(False)
MainWindow.setFont(font)
MainWindow.setMouseTracking(True)
MainWindow.setFocusPolicy(QtCore.Qt.NoFocus)
.
.
.
self.lineEditSiteX = QtWidgets.QLineEdit(self.centralwidget)
self.actionCalculate.triggered.connect(c.cal) # Here is where I'm stuck!!!!!!!!!!!!!!!!!!!!
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
In the comment above I'm trying to call a function from another file named core.py as as follows:
import gui
def cal():
val = gui.Ui_MainWindow().lineEditSiteX.value()
return val ** (1/val*2)
I simply want when someone clicks on Calculte the lineEdit value will be accessed through the core.py file. But it gives me an attributeError. How can I do it?
You have 2 errors:
Business logic should not depend on the GUI but the GUI should only use business logic.
PyQt recommends creating a class that inherits from the appropriate widget and using the class generated by Qt Designer (for more information read here).
Considering the above, the solution is:
core.py
def cal(val):
return val ** (1/val*2)
gui.py
import io
import sys
import os
import core as c
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# ...
self.lineEditSiteX = QtWidgets.QLineEdit(self.centralwidget)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(self, parent)
self.setupUi(self)
self.actionCalculate.triggered.connect(self.on_actionCalculate)
#QtCore.pyqtSlot()
def on_actionCalculate(self):
try:
val = float(self.lineEditSiteX.text())
except ValueError:
print("error")
finally:
res = c.cal(val)
print(res)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

Set scroll area initially moved

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

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

Resources