I have created a GUI application in python using PyQt5.
The steps are first I have created a ui file in Qt Designer. Then I converted that ui file into a py file using pyuic4 -o demo.ui -x demo.py in a terminal. After that I modify the py file to get dynamic values from a database. But when I have a little change in design, again I am creating the ui file, and again coverting to a py file and writing the code for the database.
So it takes a lot of time to repeat the same process. Are there any options for converting a py file to a ui file? Or any other suggestions?
You can load the .ui file in your python script using the following command :
loadUi('demo.ui', self)
There is some related examples in the folder named 'pyuic' of pyqt examples.
You should never modify the modules generated by pyuic. They are meant to be static modules that are imported into your main application.
The ui module should be created like this:
pyuic5 -o mainwindwow.py mainwindow.ui
And the main application file should look like this:
import sys
from PyQt5 import QtWidgets
from mainwindow import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.closeButton.clicked.connect(self.close)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Further information can be found in the PyQt5 docs - see Using Qt Designer.
Related
I have a fresh QtCreator installation, and I set it up to run using a fresh install of Python3.8 on which I pip-installed both pyside2 and pyside6.
When I create a new Qt for Python - Window (UI file) application, whatever I do to the UI file the window always shows up empty and with the default size when I run the app.
I've tried with a QDialog, QMainApplication, using Pyside2 or Pyside6, I've checked that it was correctly loading the UI (and the right one) - no dice. It just won't update, and appears not to have any reason not to.
Default code for completeness:
# This Python file uses the following encoding: utf-8
import os
from pathlib import Path
import sys
from PySide2.QtWidgets import QApplication, QDialog
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader
class Dialog(QDialog):
def __init__(self):
super(Dialog, self).__init__()
self.load_ui()
def load_ui(self):
loader = QUiLoader()
path = os.fspath(Path(__file__).resolve().parent / "form.ui")
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
loader.load(ui_file, self)
ui_file.close()
if __name__ == "__main__":
app = QApplication([])
widget = Dialog()
widget.show()
sys.exit(app.exec_())
(In the UI I just drag-dropped a button right in the middle and saved the file)
Am I forgetting something fundamental? I'm only used to programming in C++ using QtCreator.
I was expecting this to work right out of the box, but it's not.
This only dynamically load the UI as a new widget, with this custom class as a parent.
If I want signals and slots to work, the only thing I've found was to add a custom build step:
Command: <path to pyside6 install, use pip show to know where>\uic.exe
Arguments: <filename of the .ui file> -o <the python translation .py
which will serve as baseclass> -g python
Working directory: [your project dir]
Then signals and slots need to be connected manually, so QtCreator really only enables you to draw the user interface but all the logic still needs to be done by hand. Component variables are normally named after their UI name, but you can see for yourself in the baseclass file. This is a big step back from how QtCreator is used in C++ ("go to slot" will not work).
Code to use:
import sys
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCore import QFile
from PySide6.QtUiTools import QUiLoader
from YourGenPyFileName import Ui_YourUIName
class MainWindow(QMainWindow, Ui_YourUIName):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
if __name__ == "__main__":
app = QApplication([])
widget = MainWindow()
widget.show()
sys.exit(app.exec_())
I just try pyside6 to convert ui files into py files.
When I was using pyside2, I was writing this commande line to convert file:
pyside2-uic MainWindow.ui -o ui_mainwindow.py -x
But with pyside6, it is not working anymore: the "-x" doesn't look necessary. So you have to write:
pyside6-uic MainWindow.ui -o ui_mainwindow.py
BUT, when I run the new file generated, nothing happend. I had a look at the end of file, and it is missing a part there was with pyside2. This part of code is not here anymore:
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
What I am doing wrong ?
You're not doing anything wrong, that part of the code is added to create an "executable" version of the pyuic file, and its purpose is mainly to test it.
I don't know if the support for -x has been dropped, but that makes sense, and it won't matter a lot anyway: pyuic generated files are not intended to be executed, and should not ever be manually modified, since they should only be used as imports as explained in the official guidelines about using Designer.
The way I do it is import the class the uic created:
from ui_mainwindow import Ui_MainWindow
Then I create a QMainWindow class and instantiate the uic class.
You need to call the setupUi method on the instance.
class UI(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
...
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
win = UI()
win.show()
app.exec()
Now, you can access all the widgets via self.ui:
self.ui.myPushButton.clicked.connect(self.doSomething)
When I click "View Code" in Qt Designer (PyQt4), it tries to show the C++ code.
So, the workaround is to run:
pyuic4.bat test.ui > test.py
to convert the file to .py.
Is there a way to execute the above workaround every time "View Code" is clicked or should I have to always perform it manually?
The answer by #WithMetta in the duplicate solved my problem.
I personally load those ui files on the fly without generating python code:
something like this works for me:
import sys
from PyQt4 import QtCore,QtGui,uic
form_class, base_class = uic.loadUiType("unnamed.ui")
class MyWidget (QtGui.QWidget, form_class):
def __init__(self,parent=None,selected=[],flag=0,*args):
QtGui.QWidget.__init__(self,parent,*args)
self.setupUi(self)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
form = MyWidget(None)
form.show()
app.exec_()
I am looking for a simple example of how to directly load a QtDesigner generated .ui file into a Python application.
I simply would like to avoid using pyuic4.
For the complete noobs at PySide and .ui files, here is a complete example:
from PySide import QtCore, QtGui, QtUiTools
def loadUiWidget(uifilename, parent=None):
loader = QtUiTools.QUiLoader()
uifile = QtCore.QFile(uifilename)
uifile.open(QtCore.QFile.ReadOnly)
ui = loader.load(uifile, parent)
uifile.close()
return ui
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = loadUiWidget(":/forms/myform.ui")
MainWindow.show()
sys.exit(app.exec_())
PySide, unlike PyQt, has implemented the QUiLoader class to directly read in .ui files.
From the linked documentation,
loader = QUiLoader()
file = QFile(":/forms/myform.ui")
file.open(QFile.ReadOnly)
myWidget = loader.load(file, self)
file.close()
Another variant, based on a shorter load directive, found on https://askubuntu.com/questions/140740/should-i-use-pyqt-or-pyside-for-a-new-qt-project#comment248297_141641. (Basically, you can avoid all that file opening and closing.)
import sys
from PySide import QtUiTools
from PySide.QtGui import *
app = QApplication(sys.argv)
window = QtUiTools.QUiLoader().load("filename.ui")
window.show()
sys.exit(app.exec_())
Notes:
filename.ui should be in the same folder as your .py file.
You may want to use if __name__ == "__main__": as outlined in BarryPye's answer
Here is some example for PySide6 and Windows. (For linux you need use /, not \\)
from PySide6.QtUiTools import QUiLoader
from PySide6.QtCore import QFile
from PySide6.QtWidgets import QApplication
import sys
if __name__ == "__main__":
app = QApplication(sys.argv)
loader = QUiLoader()
file = QFile("gui.ui")
file.open(QFile.ReadOnly)
ui = loader.load(file)
file.close()
ui.show()
sys.exit(app.exec_())
For people coming from PyQt5/6 who are thoroughly confused by this:
PySide does not have the same functionality that we're used to, which is to load the ui file at the top of the window/widget subclass like so:
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
'''Load ui'''
uic.loadUi("mainwindow.ui", self)
There is nothing very similar to this in PySide.
Instead, the best thing to do is embrace the ui-file compilation that you've avoided because loading the ui file is so easy in PyQt. This has a couple of advantages
There is a performance advantage - the ui file does not need to be compiled at run time
You get type hints for all your widgets without needing to manually add them
The disadvantage is that you have to use pyside6-uic to compile the *.ui files each time you edit them, but this can be made less painful by using scripts to automate the process - either setting it up in VSCode, a batch file or a powershell script. After you've done this, the code is nice:
#ui_mainwindow is the ui_mainwindow.py file
#Ui_MainWindow is the class that was produced within that .py file
from ui_mainwindow import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainWindow, self).__init__()
'''Load the ui'''
self.setupUi(self)
So if I go into QtDesigner and build a UI, it'll be saved as a .ui file. How can I make this as a python file or use this in python?
Another way to use .ui in your code is:
from PyQt4 import QtCore, QtGui, uic
class MyWidget(QtGui.QWidget)
...
#somewhere in constructor:
uic.loadUi('MyWidget.ui', self)
both approaches are good. Do not forget, that if you use Qt resource files (extremely useful) for icons and so on, you must compile it too:
pyrcc4.exe -o ui/images_rc.py ui/images/images.qrc
Note, when uic compiles interface, it adds 'import images_rc' at the end of .py file, so you must compile resources into the file with this name, or rename it in generated code.
Combining Max's answer and Shriramana Sharma's mailing list post, I built a small working example for loading a mywindow.ui file containing a QMainWindow (so just choose to create a Main Window in Qt Designer's File-New dialog).
This is the code that loads it:
import sys
from PyQt4 import QtGui, uic
class MyWindow(QtGui.QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
uic.loadUi('mywindow.ui', self)
self.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MyWindow()
sys.exit(app.exec_())
You need to generate a python file from your ui file with the pyuic tool (site-packages\pyqt4\bin)
pyuic form1.ui > form1.py
with pyqt4
pyuic4.bat form1.ui > form1.py
Then you can import the form1 into your script.
I found this article very helpful.
http://talk.maemo.org/archive/index.php/t-43663.html
I'll briefly describe the actions to create and change .ui file to .py file, taken from that article.
Start Qt Designer from your start menu.
From "New Form" window, create "Main Window"
From "Display Widgets" towards the bottom of your "Widget Box Menu" on the left hand side
add a "Label Widget". (Click Drag and Drop)
Double click on the newly added Label Widget to change its name to "Hello World"
at this point you can use Control + R hotkey to see how it will look.
Add buttons or text or other widgets by drag and drop if you want.
Now save your form.. File->Save As-> "Hello World.ui" (Control + S will also bring up
the "Save As" option) Keep note of the directory where you saved your "Hello World" .ui
file. (I saved mine in (C:) for convenience)
The file is created and saved, now we will Generate the Python code from it using pyuic!
From your start menu open a command window.
Now "cd" into the directory where you saved your "Hello World.ui" For me i just had to
"cd\" and was at my "C:>" prompt, where my "Hello World.ui" was saved to.
When you get to the directory where your file is stored type the following.
pyuic4 -x helloworld.ui -o helloworld.py
Congratulations!! You now have a python Qt4 GUI application!!
Double click your helloworld.py file to run it. ( I use pyscripter and upon double click
it opens in pyscripter, then i "run" the file from there)
Hope this helps someone.
You can also use uic in PyQt5 with the following code.
from PyQt5 import uic, QtWidgets
import sys
class Ui(QtWidgets.QDialog):
def __init__(self):
super(Ui, self).__init__()
uic.loadUi('SomeUi.ui', self)
self.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Ui()
sys.exit(app.exec_())
The cleaner way in my opinion is to first export to .py as aforementioned:
pyuic4 foo.ui > foo.py
And then use it inside your code (e.g main.py), like:
from foo import Ui_MyWindow
class MyWindow(QtGui.QDialog):
def __init__(self):
super(MyWindow, self).__init__()
self.ui = Ui_MyWindow()
self.ui.setupUi(self)
# go on setting up your handlers like:
# self.ui.okButton.clicked.connect(function_name)
# etc...
def main():
app = QtGui.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
This way gives the ability to other people who don't use qt-designer to read the code, and also keeps your functionality code outside foo.py that could be overwritten by designer. You just reference ui through MyWindow class as seen above.
You can convert your .ui files to an executable python file using the below command..
pyuic4 -x form1.ui > form1.py
Now you can straightaway execute the python file as
python3(whatever version) form1.py
You can import this file and you can use it.
you can compile the ui files like this
pyuic4 -x helloworld.ui -o helloworld.py
In order to compile .ui files to .py files, I did:
python pyuic.py form1.ui > form1.py
Att.
in pyqt5 to convert from a ui file to .py file
pyuic5.exe youruifile.ui -o outputpyfile.py -x
(November 2020) This worked for me (UBUNTU 20.04):
pyuic5 /home/someuser/Documents/untitled.ui > /home/someuser/Documents/untitled.py
Using Anaconda3 (September 2018) and QT designer 5.9.5.
In QT designer, save your file as ui.
Open Anaconda prompt. Search for your file: cd C:.... (copy/paste the access path of your file).
Then write: pyuic5 -x helloworld.ui -o helloworld.py (helloworld = name of your file). Enter.
Launch Spyder. Open your file .py.