minimal example qtreeview for pyqt and the qt designer - python

I am trying to get a minimal example for an application designed by the qt designer with pyqt involving a QTreeView to work
1) i can start the app this way but if i push the butten, no entry in the TreeView widget is shown, i do not get any error message, and the layout looks fine, is there some kind of update method?
if you answer, please be specific, as i am still a beginner with qt and much of the documentation is written with c++ examples, and i only have some experience with basic c and python
from PyQt4 import uic, QtGui, QtCore
(Ui_MainWindow, QMainWindow) = uic.loadUiType('main_window.ui')
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.model = QtGui.QStandardItemModel()
self.connect(self.ui.pushButton_NeuesMoebel, QtCore.SIGNAL('clicked()'), self.add_item)
def add_item(self):
t = self.ui.lineEdit_Moebel.text()
if len(t) > 0:
item = QtGui.QStandardItem(t)
self.model.appendRow(item)
self.ui.lineEdit_Moebel.clear()
else:
self.ui.statusBar.showMessage('error: no text in Moebel')
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
2) additionally, is there a cleaner way to directly use the *.ui file than this, to sort of directly subclass the MainWindow of the that file? the ui stuff seems a bit messy
3) for example it would be nicer to have the add_item method in a subclass of the window created by the *.ui file, are we supposed to use the intermediate step of translating the *.ui file to a *.py file?

You just forgot to set the model on your QTreeView. Right now the tree view has no model so it never sees the data update:
def __init__(self, parent=None):
....
self.ui.treeView.setModel(self.model)
Also as a suggestion, save yourself some typing and use the new-style signal/slot connections that are more pythonic and don't make you type out signatures:
self.ui.pushButton_NeuesMoebel.clicked.connect(self.add_item)

I just came across this question and am really glad I did. It caused me to look into using the uic module, which I've been ignoring. In all the years that I've used pyqt I've always generated a .py file from the designer .ui file, and then importing the generated file as a module.
Using uic instead to directly load the .ui file saves a step and simplifies things quite a bit. It's easy to do.
So yes, in answer to question #2 there's a simpler way than calling the ui stuff:
from PyQt4 import uic, QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self,parent)
uic.loadUi('main_window.ui',self)
....

Related

using qt with custom loop in python

I have been experimenting around with using QT in python3 and figured out how to make a simple .ui file and import it directly into a python program. However I have to use python QT app while I would like to have my own custom loop in order to be able to add things to it. So what I have now is:
import sys
from PyQt4 import QtCore, QtGui, uic
class MyWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.desktop = uic.loadUi('mytest.ui')
self.desktop.show()
if __name__ == '__main__':
app = QtGui.QApplication.instance()
window = MyWindow()
sys.exit(app.exec_())
I've played around a bit with PGU where I have been able to do this with what would be
while True:
window.loop()
in the main which allows me to put in my own extra code that is unrelated to the GUI without dealing with multiple threads. However I have been unable find some equivalent to "loop" in qt and searching for "qt custom loop/update/blit python" hasn't found anything relevant besides suggestions to add a 0 second timer to my app and place extra code there which seems... inelegant to me. I would like to import a GUI into my app rather then building my app around a GUI.
Edit: Here is my updated code taking Phyatt's answer into account for anyone else looking for the same answer I was.
import sys
from PyQt4 import QtGui, QtCore, uic
class TestApp(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = uic.loadUi('mytest.ui')
self.ui.show()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
win = TestApp()
app.processEvents()
while True:
app.processEvents()
Instead of using your own custom loop, the more common way to do that is to have a timer event scheduled on the Qt loop, or to launch another thread.
If you still really wanted to use your own loop, you need to manually call QApplication.processEvents() in your loop and it probably should work.
http://qt-project.org/doc/qt-4.8/qcoreapplication.html#processEvents
http://doc.qt.io/qt-5/qtimerevent.html#details
MyWindow.start(100) # start the built in timer event for that QObject 10 times a second
And then in MyWindow put def timerEvent and it should work.
Hope that helps.

accessing QtGui objects created by pyQt

So I'm quit new to working with UI in python. I'm not really grasping a core concept and i think this simple question will help flip on the light switch.
As seen in the code snippet below, I imported a ui file made in Qt. This ui has a pushbutton on it. How do I make a click event on that button? I have gone through tutorials on how to code a button and use it. I understand that. It is the question of how to access the objects and manipulate the objects that are created by the ui file. What i really want to do is see how to perform a function (or instantiate a class or whatever) when a button is clicked. that function being one that i wrote. baby steps though. any answers and elaborations would be appreciated.
import sys
from PyQt4 import QtGui, uic, QtCore
class MyWindow(QtGui.QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
uic.loadUi('myWidget.ui', self)
self.show()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MyWindow()
sys.exit(app.exec_())
like i said. very simple question but I'm just not really grasping the core concept here. thanks you.
self.ui=uic.loadUi('curveViewer.ui', self)
#where `your_pushbutton` is the button name specified in your .ui file:
self.ui.your_pushbutton.clicked.connect(self.onBtnClicked)
or just:
uic.loadUi('curveViewer.ui', self)
self.your_pushbutton.clicked.connect(self.onBtnClicked)
then define method onBtnClicked inside your class MyWindow:
def onBtnClicked():
print 'pushbutton clicked'
see New-style Signal and Slot Support
btw, it's better to remove self.show(), and make it:
window = MyWindow()
window.show()

Horizontal Header to Large in QtDesigner

I am building a Gui in QtDesigner but i do not understand how i add a "dynamical property":
I try to add a QTable Widget but the Header of the Columns are to large (The Text is just 2 letter in the Columns).
For Space reasons in my Gui i just need them to be as big as the text is (or let us say 4 letters)
i found the
QHeaderView::ResizeToContents method but i do not know how to use it- is there a way to do this in QtDesigner?
I am new to this and i do not know how to change the code behind the Gui...
For PyQt, the main purpose of Qt Designer is to create the main GUI structure of your application. It only allows a subset of the available properties to be modified for any given widget, and it cannot be used to write the application's main logic.
Instead, the idea is to generate a python module from the ui file created by Qt Designer, and then import it into your application where you can do the remaining setup code, connect signals, write all the event handlers, etc.
Let's say you've created a ui file with Qt Designer and named it mainwindow.ui.
You would then generate the python module like this:
pyuic4 -o mainwindow_ui.py mainwindow.ui
Next, you would write a separate main.py script that imports the GUI classes from the generated module, and creates instances of them as needed.
So your main.py would look something like this:
from PyQt4 import QtCore, QtGui
from mainwindow_ui import Ui_MainWindow
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
header = self.tableWidget.horizontalHeader()
header.setResizeMode(QtGui.QHeaderView.ResizeToContents)
...
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
The base-class here must be same as the top-level widget in Qt Designer (i.e. usually either QMainWindow, QDialog, or QWidget). Also, the objectName property of the top-level widget is used to generate the classname of the imported GUI class (with "Ui_" prepended to it). The example above assumes this was set to "MainWindow".
The objectName properties of all the other widgets will become attributes of the MainWindow class, so that they can be accessed easily in the rest of your code. Because of this, it's important that you always set the objectName properties to descriptive names (i.e. not "pushButton_1", "pushButton_2", etc).

Correct way to address Pyside Qt widgets from a .ui file via Python

I have created a GUI with Qt Designer and accessed it via
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
MainWindow = loadUiWidget("form.ui")
MainWindow.show()
children = MainWindow.children()
button1 = MainWindow.QPushButton1
"children" does already contain the widgets "QPushButton1", "QTextBrowser1" created in the UI but shouldn't the be accessed by the recoursive findChildren() method?
What is an elegant way to access the widgets of the .ui File?
References:
Find correct instance,
Load .ui file
Since widget names in Qt Designer must be unique, the hierarchy (at least for getting references to the widgets) is flattened (with no risk of conflict), and so the best way is just to access them via:
loader = QtUiTools.QUiLoader()
ui = loader.load('filename.ui', parent)
my_widget = ui.my_widget_name
This would place a reference to the widget called 'my_widget_name' in Qt Designer in the variable my_widget.
I would say the above is the most pythonic way of accessing the widgets created when you load the .ui file.
There are two disadvantages of loading UI at run time:
overhead each time the program is run (actually, each time the loader is used)
lack of support of code completion and checking, since IDE doesn't know the code behind ui until the uifile has been loaded.
An alternative, assuming you are using the modern version of PySide called "Qt for Python", is to "compile" the .ui file to a Python class (see docs). For this, after saving filename.ui, execute
pyside2-uic filename.ui -o ui_mainwindow.py
while within your virtual environment, if any. The new class will be called Ui_MainWindow. Assuming you have a text_box widget in your UI, you can now access its properties and methods. Here is a full working example:
import sys
from PySide2.QtWidgets import QApplication, QMainWindow
from ui_mainwindow import Ui_MainWindow
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.text_box.setPlainText('test') # here we are addressing widget
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Notes:
pyside2-uic should be called after every change of the .ui file. This is a disadvantage of this approach in comparison to OP. It also means that you should either version-control both .ui and .py files for your UI, or somehow call uic during deployment.
The big advantage is that IDE like PyCharm has access to all widget methods and properties for autocompletion and code checking.
As of today, pyside2-uic creates non-PEP8 compliant code. However, as long as you give your widgets PEP8-compliant names, your own code will be OK.

Initialization completed event in QT4 GUI

I have a QT4 and python 2.4 based GUI. The user starts using it by opening a file. In addition to explicit browsing, I would like to allow the user to specify a file to open as a command line argument. I am looking for some event in the QMainWindow (or wherever) that would allow me to detect when the application completed its initialization and is ready for user interaction at which point I could automatically open the file and populate the widgets. So far I could not find anything better than overriding showEvent which is not exactly it because the main window is still not visible at this point. It might be okay but I am looking for a proper way to do this. In some other UI toolkits that I have used in the past that would be something like “main form layout completed” event that would signal that the UI is safe to deal with. Is there something similar in QT4? I am running this on Linux if that matters.
You insights are greatly appreciated.
You don't need an event here. It is guaranteed that everything is loaded after __init__() and show() have run, so you can just put your code for the file opening after that.
import sys
from PyQt4 import QtGui
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.setupUI()
self.show()
# normal __init__ done
if len(sys.argv) > 1:
with open(sys.argv[1]) as f:
# do stuff with file
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())

Categories

Resources