Comments (17)
Thanks @bpabel.
Per the python mailing list discussion
Would it be possible to link to this discussion?
Here is an example of an implementation for PySide that accepts the same arguments
Excellent, would you happen to know whether the same implementation works for PySide2? If you put a pull-request in, we could have it run through tests on each platform, Python version and Qt distribution. That should get the conversation started.
As I'm not a user of loadUi myself, it would also be lovely to have one or more usage examples so that we implement it in a way that makes sense to you.
from qt.py.
Would it be possible to link to this discussion?
This was from the closed 3DPRO mailing list. I asked Abel to post an issue :)
@mottosso Did you get my invite?
Excellent, would you happen to know whether the same implementation works for PySide2?
I've made a gist where this works in PySide2:
https://gist.github.com/fredrikaverpil/0a89b174c9d29bc585f11d250adf2a7c
I think Abel's request makes a lot of sense. I omitted additional arguments to the load_ui
convenience function but the gist seems to show a clear way to support that. We should do it!
from qt.py.
Would it be possible to post a minimal example ui
file, along with how it is used today, and how you would like it to be used with this feature?
from qt.py.
Would it be possible to post a minimal example ui file, along with how it is used today, and how you would like it to be used with this feature?
I could do a PR, but I won't have time for it until mid August 😢 as I'm on vacation with my family 😄
However, here's an example UI file which we could use for this example. Today, we can access the widgets from the ui file like this:
import sys
from Qt import QtWidgets
from Qt import load_ui
class Hello(QtWidgets.QWidget):
def __init__(self):
super(Hello, self).__init__()
self.ui = load_ui('main_window.ui')
print(self.ui.boilerPushButton) # a pushButton widget from main_window.ui
app = QtWidgets.QApplication(sys.argv)
window = Hello()
window.ui.show()
sys.exit(app.exec_())
However, we can't load the UI widgets directly into self
and make the pushButton available like this: self.boilerPushButton
. So let's say you load three UI files and want all of their widgets to be accessed like self.widgetName
. Today this is possible in PyQt (by providing a second argument to uic.loadUi
which load_ui
wraps) but not in PySide (not without pysideuic
). But with @bpabel's gist, this seems doable with a custom QUiLoader
class (really nice since it doesn't require the pysideuic
module which isn't always available, e.g. missing in Nuke).
Here's a full example of me loading two UIs with the current behaviour of load_ui
and it shows how you need to load each UI into separate objects:
https://github.com/fredrikaverpil/pyvfx-boilerplate/blob/master/boilerplate.py#L164-L165
This is what we want to be able to do with an optional second argument to load_ui
. So instead of the example above, we could do this:
class Hello(QtWidgets.QWidget):
def __init__(self):
super(Hello, self).__init__()
self.ui = load_ui('main_window.ui', self) # Load widgets into self
print(self.boilerPushButton) # the button is now available in self
Of course, you could also load widgets into something else than just self
. The point is you want control on where your UI file's widget ends up being accessible from.
@mottosso if you like, we can assign this to me, but I won't have time for it until a couple of weeks away.
It would basically entail updating pyside_load_ui
, pyside2_load_ui
, pyqt4_load_ui
and pyqt5_load_ui
to support this optional argument.
from qt.py.
Sorry, I edited my prevous post a lot to clarify things a bit with better examples. Please re-read it if you already read it.
from qt.py.
If we were to write tests for this, we'd need to store a .ui file in the repository. How do you feel about that, @mottosso ?
We could create a main_window.ui file in a data
dir?
from qt.py.
We could, but I'd rather keep it contained in the test module.
If you hand me a .ui snippet, I can show you how I mean.
from qt.py.
If you hand me a .ui snippet, I can show you how I mean.
Will this do?
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>125</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
from qt.py.
Here's what I had in mind.
def test_pyside_load_ui():
"""load_ui works well"""
ui = """\
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>125</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>"""
with tempfile.NamedTemporaryFile(suffix=".ui") as f:
f.write(ui)
f.seek(0)
with pyside():
import Qt
widget = Qt.load_ui(f.name)
Ideally then, the .ui file would only contain parts we are actually testing. In this case, perhaps QStatusBar and explicit widths are less important in the interest of readability.
from qt.py.
Ah, yes. That's an excellent idea.
from qt.py.
It might not seem like a big deal today. From experience with maintaining external files with tests, I find that this works fine initially, but then as the project is updated, tests change, and the external files will need to branch out to cover both in order to be backwards compatible.
With this approach, even though it makes each test bigger and more repetitive, tests and data change together and should be easier to maintain long-term.
from qt.py.
Yep. Agreed.
from qt.py.
Hm, so I'm wondering about one thing. It looks like we could add a custom class to the _pyside
and _pyside2
functions. First, it's quite unconventional to define a class inside a function, but it will inherit QtUiTools.QUiLoader
from PySide/PySide2 and will throw an error if Qt.py is using PyQt4/PyQt5.
Right now, I'm just putting the class definition in both these functions. Any idea on how we could structure this more nicely?
from qt.py.
Never mind, I think I found a solution.
from qt.py.
@fredrikaverpil If you can, please post an example or two of the intended usage before looking at implementing this.
What I'm looking for is to have tests in place before the implementation starts. TDD style.
from qt.py.
Yes, I'm doing the tests now. But as I had to rebuild the docker container I now am having issues with nosetests complaining about not being able to connect to an X server:
...
...
Raise ImportError if sip API v1 was already set (Python 2.x only) ... ok
load_ui works well ... ERROR
nosetests: cannot connect to X server
Even if I remove my load_ui test, I get the X server error. It seems nosetests broke after I re-built the container from scratch. There are no detailed error messages since nosetests errors out with this X server notice before it can get there.
Do you see this on your end too if you rebuild your container?
Here's my test:
def test_pyside_load_ui():
"""load_ui works well"""
ui = """\
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>125</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>"""
with tempfile.NamedTemporaryFile(suffix=".ui") as f:
f.write(ui)
f.seek(0)
with pyside():
from Qt import QtWidgets, load_ui
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QMainWindow.__init__(self, parent)
load_ui(f.name, self)
assert self.pushButton
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
# window.show()
# app.exec_()
I intend to remove QStatusBar, QMenuBar etc as soon as I get this example working.
from qt.py.
See #81
from qt.py.
Related Issues (20)
- [HOW TO] Set preferred binding from code before import HOT 2
- name 'QGuiApplication' is not defined HOT 3
- QT-Py internal NEOPixel HOT 5
- _wrapInstance pointer type assert message in Py3 HOT 1
- looks like QtGui.QGuiApplication is not wrapped... HOT 1
- Table Drop Event and loadUi with PySide2 HOT 3
- Add PySide6 support HOT 20
- https://github.com/spyder-ide/qtpy/issues/348 HOT 6
- QtCompat.isValid() Not Available for All Qt Objects HOT 8
- How to add menubar in QT?
- Drop PyQt because it may be illegal to import a GPL lib from a lib under MIT HOT 1
- TypeError: Expected 4 or 5 arguments, got 3. HOT 1
- Is it possible to add support for QIdentityProxyModel HOT 1
- Change of types-PySide2 breaks Python 2 compatibility HOT 10
- TypeError: 'PySide2.QtWidgets.QWidget' called with wrong argument types
- partially initialized module 'Qt' has no attribute 'QtGui' (most likely due to a circular import)
- Convert does not convert files built with pyside2-uic 5.15.2 HOT 1
- signal.connect() TypeError in pyqt5 when signal has an argument HOT 9
- stubs missing signal.connect, disconnect and emit HOT 6
- Cannot install v1.3.8 from sdist HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from qt.py.