Python: Access class method variable from another file - python-3.x

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

Related

pyqt5 button click not working from my second window

i am stuck in call function from pushButton.
in my project:
app.py, which is the main file to run the project.
ui_mainWindow.py is the file consist of tab widget.
Account.py is the converted file from account.ui
main_Account.py is the file where i import Account.py file.
account_handler.py is the file where consist of functions.
now when i run my project by running app.py ,it will show all contents of ui_mainWindow.py .now if i choose account tab from tabwidget than it will show all contents of mainAccount.py. now if i hit a button from mainAccount.py than function will be call from account_handler.py.
everything working fine but while i hut pushButton nothin happen.
this is my previous post : PyQt5 push button method called from separate python file ,
i follow this separately and this working fine, but in my project samecode not working. can anyone tell me where i am wrong!
app.py
from importlib import reload
import PyQt5.QtCore as QtCore
from PyQt5.uic import loadUi
from PyQt5.QtWidgets import QMainWindow,QApplication
import sys
import files.interfaces.ui_mainWindow
import files.interfaces.dashboard
reload(files.interfaces.dashboard)
import files.main_Interfaces.mainAccount
reload(files.main_Interfaces.mainAccount)
import files.interfaces.account2
reload(files.interfaces.account2)
class MainWindow(QMainWindow, files.interfaces.ui_mainWindow.Ui_MainWindow):
def __init__(self):
# Base class
QMainWindow.__init__(self)
self.ui = files.interfaces.ui_mainWindow.Ui_MainWindow()
self.ui.setupUi(self)
self.setWindowTitle("PORTFOLIO ACCOUNTING")
# import tab1
self.TabWidget = QtWidgets.QWidget()
ui = files.interfaces.dashboard2.Ui_Form()
ui.setupUi(self.TabWidget)
self.ui.tabWidget.insertTab(0, self.TabWidget, "Dashboard")
# import tab2
self.TabWidget = QtWidgets.QWidget()
ui = files.main_Interfaces.mainAccount.MainWindow()
ui.setupUi(self.TabWidget)
self.ui.tabWidget.insertTab(1, self.TabWidget, "Account")
def main():
app = QtWidgets.QApplication(sys.argv)
app.setApplicationName("Portfolio Accounting")
application = MainWindow()
application.show()
app.exec_()
if __name__ == '__main__':
main()
main_Account.py
from PyQt5 import QtCore, QtGui, QtWidgets
from files.interfaces.account import Ui_Form
from event_handler.account_EventHndler import function2
class MainWindow(QtWidgets.QMainWindow,Ui_Form):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.pushButton_2.clicked.connect(function1)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
account_handler.py
def function1():
print("function called")
You code is a bit confusing since you use the same class names in different modules and there is an inconsistencies between the names of the modules you are importing and the names of the .py files you provided but I'm assuming that files.main_Interfaces.mainAccount.MainWindow refers to mainWindow in main_Account.py. In that case, in app.MainWindow.__init__ tab2 should probably be something like
# import tab2
self.TabWidget = files.main_Interfaces.mainAccount.MainWindow()
self.ui.tabWidget.insertTab(1, self.TabWidget, "Account")

how to set a function output as a signal in pyqt5

I want to display the logged in user os.getlogin() displayed in a label widget.
So far I need to set a custom signal and connect it to the label
here is my (not functioning) code, hope you can guide my how to write it properly
import sys
import os
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
class UserTest(qtw.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# your code will go here
user_in_label = qtw.QLabel()
layout = qtw.QVBoxLayout()
layout.addWidget(user_in_label)
# funktionen
self.trigger = qtc.pyqtSignal(str)
# fire signal to slot
self.set_signal.connect(user_in_label.setText)
# your code ends here
self.show()
def set_signal(self):
active_user = os.getlogin()
self.trigger.emit(active_user)
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
w = UserTest()
sys.exit(app.exec_())
self.set_signal.connect(user_in_label.setText)
this line is missing an object, do I need to set a new class for this take, seems like nonsense
Try it:
import sys
import os
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
class UserTest(qtw.QWidget):
trigger = qtc.pyqtSignal(str) # +++
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
user_in_label = qtw.QLabel()
layout = qtw.QVBoxLayout(self) # + self
layout.addWidget(user_in_label)
layout.addWidget(qtw.QPushButton('Click me', clicked=self.set_signal)) # +++
self.trigger.connect(user_in_label.setText) # +++
def set_signal(self):
active_user = os.getlogin()
self.trigger.emit(active_user)
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
w = UserTest()
w.show()
sys.exit(app.exec_())
Update
can you explain why you relocate trigger = qtc.pyqtSignal(str) above init ? and any suggestions how to set active user automatically to the label without the push button?
trigger must be a class attribute
import sys
import os
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
from PyQt5 import QtGui as qtg
class UserTest(qtw.QWidget):
trigger = qtc.pyqtSignal(str)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
user_in_label = qtw.QLabel()
layout = qtw.QVBoxLayout(self)
layout.addWidget(user_in_label)
# layout.addWidget(qtw.QPushButton('Click me', clicked=self.set_signal))
self.trigger.connect(user_in_label.setText)
self.set_signal() # +++
def set_signal(self):
active_user = os.getlogin()
self.trigger.emit(active_user)
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
w = UserTest()
w.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_())

Start the script in PyQt5 and python3 [duplicate]

I have created a form using PyQt4 which has a push button. On this push button I want to call another python script which looks like this:
File1.py:
import sys
from PyQt4 import QtCore, QtGui
from file1_ui import Ui_Form
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
File1_ui.py
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(400, 300)
self.pushButton = QtGui.QPushButton(Form)
self.pushButton.setGeometry(QtCore.QRect(120, 200, 95, 20))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.retranslateUi(Form)
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8("clicked()")), Form.close)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.translate("Form", "Close", None, QtGui.QApplication.UnicodeUTF8))
File2.py
import sys
from PyQt4 import Qt
from taurus.qt.qtgui.application import TaurusApplication
app = TaurusApplication(sys.argv)
panel = Qt.QWidget()
layout = Qt.QHBoxLayout()
panel.setLayout(layout)
from taurus.qt.qtgui.panel import TaurusForm
panel = TaurusForm()
model = [ 'test/i1/1/%s' % p for p in props ]
panel.setModel(model)
panel.show()
sys.exit(app.exec_())
File1_ui.py is created from the Qtdesigner and then I am using File1.py to execute it.So File2.py when executed alone opens up a panel and displays few attributes.I want this script to be called on the button click in the first form(file1.py) which I created using Qtdesigner.Could you let me know how I could achieve this functionality.Thanks.
You will need to make some modifications to File2.py to make the appropriate calls depending on whether it is running standalone or not. When you are launching the script via File1.py there will already be a QApplication instance with event loop running, so trying to create another and run its event loop will cause problems.
Firstly, move the core part of your script into its own function. This will allow you to easily call it from File1.py. You can then handle the case where the script is running standalone and needs to create a QApplication instance and start its event loop. (I am not familiar the the taurus library you are using, but you can probably substitute TaurusApplication for QtGui.QApplication)
File2.py:
import sys
from PyQt4 import QtCore, QtGui
def runscript():
panel = QtGui.QWidget()
layout = QtGui.QHBoxLayout(panel)
return panel # Must return reference or panel will be deleted upon return
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
panel = runscript()
panel.show()
sys.exit(app.exec_())
Assuming your files are in the same directory you can simply write import File2 and use File2.runscript() to run your code. You then just need to connect the function to your pushbuttons clicked() signal to run it. The only problem here is that the reference to the QWidget returned from the runscript() function will be lost (and the object deleted) if you connect directly to runscript(). For this reason I created a method launch_script() which saves a reference in MyForm.
File1.py:
import sys
from PyQt4 import QtCore, QtGui
from file1_ui import Ui_Form
import File2
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
# This is a bit of a hack.
self.ui.pushButton.clicked.connect(self.launch_script)
def launch_script(self):
self.panel = File2.runscript()
self.panel.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
I don't use Qt Designer, so I don't know the correct way to go about connecting the signal to launch_script(). The code I have written should work, but obviously violates OOP principles and is dependent on the name of the pushbutton widget assigned by the software.

Pyqt lunch separate Qtapplications in separate process

So what i would like to do is from the main Qt application start a bunch of separate Qt applications each on separate processes ... do their job then report to the main application when finished.
Could you guys point me in the right direction . I tried with multiprocessing but i get stuck initializing the separate Qt applications
Thank you
Something like this ... which is wrong
import sys
import multiprocessing
from multiprocessing import Pool
from PyQt4 import QtCore, QtGui ,QtNetwork
from PyQt4 import QtWebKit
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
from PyQt4.QtGui import QApplication
class SimpleWin(QtGui.QWidget):
def __init__(self, parent=None):
super(SimpleWin, self).__init__(parent)
self.buton = QtGui.QPushButton("START")
self.buton.clicked.connect(self.RunJob)
hbox = QtGui.QHBoxLayout()
hbox.addWidget(self.buton)
self.setLayout(hbox)
def RunJob(self):
print "RUUN"
jobs = []
for i in range(5):
p = multiprocessing.Process(target=Render,)
print i
jobs.append(p)
p.start()
class Render(QWebView,multiprocessing.Process):
def __init__(self, prox ):
self.app = QApplication(sys.argv)
QWebPage.__init__(self)
# self.crawl()
self.load(QUrl("http://www.ip-score.com/"))
self.show()
self.app.exec_()
def main():
app = QtGui.QApplication(sys.argv)
browse = SimpleWin()
browse.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Resources