Use separate interface file with PyQt - python

I have an interface file generated from QtDesigner that I want to keep the same in case of changes.
Have a main file called application.py handle all the functions, and one file strictly for interface stuff.
I am using PyQt5.
I have not been able to find any tutorials on this specific question, any pointers would be helpful.
Code from YatsiInterface.py (shorten)
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_YatsiWindow(object):
def setupUi(self, YatsiWindow):
YatsiWindow.setObjectName("YatsiWindow")
YatsiWindow.resize(800, 516)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("Terraria.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
YatsiWindow.setWindowIcon(icon)
self.windowLayout = QtWidgets.QWidget(YatsiWindow)
self.windowLayout.setObjectName("windowLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.windowLayout)
self.quitButton.setObjectName("quitButton")
self.buttonsLeftLayout.addWidget(self.quitButton)
YatsiWindow.setCentralWidget(self.windowLayout)
self.statusbar = QtWidgets.QStatusBar(YatsiWindow)
self.statusbar.setObjectName("statusbar")
YatsiWindow.setStatusBar(self.statusbar)
self.retranslateUi(YatsiWindow)
QtCore.QMetaObject.connectSlotsByName(YatsiWindow)
def retranslateUi(self, YatsiWindow):
_translate = QtCore.QCoreApplication.translate
YatsiWindow.setWindowTitle(_translate("YatsiWindow", "Yatsi - Server Interface"))
self.quitButton.setText(_translate("YatsiWindow", "Quit"))
How can I use self.quitButton.clicked.connect(QtCore.QCoreApplication.instance().quit()) with the above code? I know to import the file with from YatsiInterface import Ui_YatsiWindow but I'm in the dark as how to create button functions without editing the interface file.
Edit:
I'll add my broken code below.
import sys
from YatsiInterface import Ui_YatsiWindow
from PyQt5 import QtCore, QtGui, QtWidgets
app = QtWidgets.QApplication([])
YatsiWindow = QtWidgets.QMainWindow()
ui = Ui_YatsiWindow()
ui.setupUi(YatsiWindow)
# Here's the bad part
ui.setupUi.btn.clicked.connect(QtCore.QCoreApplication.instance().quit)
# Up there ^
YatsiWindow.show()
sys.exit(app.exec_())
Thanks for your help.

This would be the way to connect the signal
ui.quitButton.clicked.connect(QtCore.QCoreApplication.instance().quit)
That being said, you probably don't want to do this. You should probably connect to the .close method of the window. When the window closes, by default, Qt will exit the event loop and quit.
ui.quitButton.clicked.connect(YatsiWindow.close)

from YatsiInterface import Ui_YatsiWindow
from PyQt5 import QtCore, QtGui
class my_application(QtGui.QWidget, Ui_YatsiWindow):
def __init__(self):
super(my_application, self).__init__()
self.setupUi(self)
self.quitButton.clicked.connect(self.my_mythod)
def my_method(self):
pass #all your code for the buttons clicked signal
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
ui = my_application()
ui.show()
sys.exit(app.exec_())
This my_application class is inheriting your user interface class. Now, you can write your button related functions without editing the user interface file.
self.quitButton.clicked.connect(self.close)
this will close your user interface when button is clicked.

Related

How to call "flash.ocx" with python by filename

I want to create a player using "flash.ocx".
It looks like this.
from PyQt5 import QtCore, QtGui, QAxContainer, QtWidgets
import pickle
class Ui_Flash(QAxContainer.QAxWidget):
def __init__(self, parent=None):
super(Ui_Flash, self).__init__()
self.resize(800, 600)
self.setControl("{D27CDB6E-AE6D-11cf-96B8-444553540000}")
self.dynamicCall("LoadMovie(long,string)", 0, r"test.swf")
self.show()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
ui = Ui_Flash()
ui.show()
sys.exit(app.exec_())
However, this method is implemented using the COM interface. It can use either "ProgID" or "CLSID".
But I want to find an implementation method that can be called directly by the file name.
It looks like ...
self.setControl("D:\\Flash.ocx") # The "self.setControl" func is an example, which does not mean that the example is correct.
You can use pyqt or other UI designs, such as Tkinter.
So, how do I do it?
Thank you for your help.

(PyQt) QVBoxLayout shrink upon multiple loading of addWidget

Why is the layout shrinking like this and other times going back to normal?
I've created several separate UI files in QtDesigner, one is the MainWindow and the other is a widget for Loading Data.
In order to work with these files, I've created separate child classes of each UI file. In order to add a new widget to the MainWindow I've created a addWidget() function; it works by adding a particular widget to the scrollarea layout. You can see this function in MainWindow.py
Here is the code for __main__.py
import multiprocessing as mp
import os.path
import sys
import time
from PyQt5 import QtGui
from PyQt5 import QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import *
from point_spectra_gui.future_.functions import *
from point_spectra_gui.future_.util import delete
from point_spectra_gui.future_.util.excepthook import my_exception_hook
def new():
p = mp.Process(target=main, args=())
p.start()
def connectWidgets(ui):
ui.actionLoad_Data.triggered.connect(lambda: ui.addWidget(LoadData.Ui_Form))
def main():
sys._excepthook = sys.excepthook
sys.excepthook = my_exception_hook
app = QtWidgets.QApplication(sys.argv)
mainWindow = QtWidgets.QMainWindow()
ui = MainWindow.Ui_MainWindow()
ui.setupUi(mainWindow)
connectWidgets(ui)
mainWindow.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Here is the code for MainWindow.py
from PyQt5 import QtWidgets
from point_spectra_gui.future_.functions import *
from point_spectra_gui.future_.util import *
from point_spectra_gui.ui import MainWindow
class Ui_MainWindow(MainWindow.Ui_MainWindow):
def setupUi(self, MainWindow):
self.MainWindow = MainWindow
super().setupUi(MainWindow) # Run the basic window UI
self.menu_item_shortcuts() # set up the shortcuts
def addWidget(self, object):
widget = object()
widget.setupUi(self.scrollArea)
self.widgetLayout = QtWidgets.QVBoxLayout()
self.widgetLayout.setObjectName("widgetLayout")
self.verticalLayout_3.addLayout(self.widgetLayout)
self.widgetLayout.addWidget(widget.get_widget())
def menu_item_shortcuts(self):
self.actionExit.setShortcut("ctrl+Q")
self.actionCreate_New_Workflow.setShortcut("ctrl+N")
self.actionOpen_Workflow.setShortcut("ctrl+O")
self.actionRestore_Workflow.setShortcut("ctrl+R")
self.actionSave_Current_Workflow.setShortcut("ctrl+S")
Here is the code of the child class LoadData.py
from PyQt5 import QtWidgets
from point_spectra_gui.ui.LoadData import Ui_loadData
class Ui_Form(Ui_loadData):
def setupUi(self, Form):
super().setupUi(Form)
self.connectWidgets()
def get_widget(self):
return self.groupBox
def connectWidgets(self):
self.newFilePushButton.clicked.connect(lambda: self.on_getDataButton_clicked())
# self.get_data_line_edit.textChanged.connect(lambda: self.get_data_params())
# self.dataname.textChanged.connect(lambda: self.get_data_params())
def on_getDataButton_clicked(self):
filename, _filter = QtWidgets.QFileDialog.getOpenFileName(None, "Open Data File", '.', "(*.csv)")
self.fileNameLineEdit.setText(filename)
if self.fileNameLineEdit.text() == "":
self.fileNameLineEdit.setText("*.csv")
**Edit
Upon trying this again and then shrinking the window. The layout goes back to normal.
This to me tells me it's not a problem with my code, it's the way the Qt handles the adding of widgets. I still do not understand why this is happening though. So any insight into how this is happening is very much appreciated.
This problem is with the Form.resize() inside the generated code.
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(400, 300)
To fix this you'll need to go into QtDesigner and set the geometry back to it's default the Layout size by clicking the red circled item.
This, in essence, deletes the resize method call
You can then convert again with pyuic

Python: QT5 include ui.py in main python script

this might be an basic question, but I didn't found a working solution yet:
This is my first Python UI Script... I have the idea of putting the UI in one file without any functionality and putting all the actual code and algorithms into another file, but I don't know if this is good practice or not and how to make this work.
I have created an UI with GTDesigner and converted this into MainWindowPy.py by using pyuic5.
This gave me:
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
[...]
def retranslateUi(self, MainWindow):
[...]
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_())
Now I want to leave this MainWindowPy.py untouched, because the UI can change in the further delevopment.
How can I link and run this file in my MainApplication.py script and how can I access UI-elements like buttons?
I tried wrapping the whole UI-code in a function and then imported this as a module in MainApplication.py and called the function through this module. It worked, but that's not "untouched".
I know about subprocess.Popen(), but maybe there is a better way?
The code generated in this case is a mixin class. To use it in a different file you simply import it and create a new class with two base classes, one which is the Qt Class you want it to be and the second which is the mixin class from your uic generated file. In the init of your new class you must run the init method of the primary base class, and the setupUi method of the mixin class:
from MainWindowPy import Ui_MainWindow
from PyQt5 import QtWidgets
class myMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(myMainWindow, self).__init__(parent) # call init of QMainWindow, or QWidget or whatever)
self.setupUi(self) # call the function that actually does all the stuff you set up in QtDesigner
now to use it, you initiate your custom class that you made
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = myMainWindow()
MainWindow.show()
sys.exit(app.exec_())

how to call a python script on button click using PyQt

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.

How does one make a button in the main window open a different window?

I am very new to this and have used the Qt Designer to make a very simple main window ui. The first functionality I want in my project is for a button to open a different window when clicked.
So basically I have the file autoGenUI.py that is generated using pyside-uic which includes
from PySide import QtCore, QtGui
class AutoGeneratedUI(object):
def setupUi(self, MainWindow):
#Auto generated code
def retranslateUi(self, MainWindow):
#Auto generated code
This all works fine of course because the Qt designer made it. I then have my own .py file that is basically my application stuff.
It looks like this:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from autoGenUI import *
class MyMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.ui = AutoGeneratedUI()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
myMainWindow = MyMainWindow()
myMainWindow.show()
sys.exit(app.exec_())
My button is called self.pushButton in the auto generated python UI. I would like to design another window and then call that window but for now anything will do. I just don't know where to put the code to make my button do something.
I tried to follow the docs but couldn't get anything to work.
Any help is greatly appreciated.
Thanks
You need to connect the clicked signal of pushButton to a method such as on_button_clicked():
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.ui = AutoGeneratedUI()
self.ui.setupUi(self)
# connect the clicked signal to on_button_clicked() method
self.pushButton.clicked.connect(self.on_button_clicked)
def on_button_clicked(self):
print "button clicked"
# here is the code to open a new window

Categories