<html>
<head>
<style type="text/css">
body,p,td,div,span{
        font-size:14px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; color: #212121;
};
body p{
        margin:0px;
}
</style>
</head>
<body><div>@ Maurizio<br></div><div>Thank you so much for clearing the nodal in my brain. Beautiful music you make, btw. <br></div><div>Regards Hans<br></div><div><br></div><div><br></div><blockquote style="border:0;border-left: 2px solid #22437f; padding:0px; margin:0px; padding-left:5px; margin-left: 5px; "><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>Here the link to the SO Question mentioned in the mail below:</div><div><a target="_blank" class="blue" href="https://stackoverflow.com/questions/46515179/subclassing-of-widgets-which-are-loaded-by-uic-loadui">https://stackoverflow.com/questions/46515179/subclassing-of-widgets-which-are-loaded-by-uic-loadui</a></div></blockquote><div><br></div><div>After many years of playing around with PyQt I've found "my" optimal setup for a good environment allowing simpler coding and integration with .ui files created within Designer. I'd also like to add that the documentation about this is not always clear, and it sometimes "makes sense" only whenever you've completely understood how Qt, PyQt and the whole GUI environment works.<br></div><div><br>Let me share how I usually work.</div><div><br></div><div>- All main windows (QMainWindow and QDialog, but QWidget too) are only saved to .ui files, and I load their ui through loadUi(). While "building" with pyuic might be better for various reasons (paths, mainly), working with plain raw ui files avoids confusion: sometimes (a lot of times, in my case, it can be simple fatigue or distraction after hours of coding) you edit a widget in Designer and then you forget that you've to recreate the python ui file, then after minutes of trying to understand why something is not working as it should, you remember... This is annoying, and makes you lose a *lot* of time.</div><div>- Due to the previous point, all windows that use an .ui file only have to inherit from their base Qt class; the only drawback is that you've to be careful to never use object names that might conflict with python naming standards and QWidget/QObject property/function names: for example, "style", "cursor" or "layout". The huge advantage is that you don't need to refer to the "self.ui", and everything is transparently available as a property/method of the main widget class.</div><div>- All custom widgets of a GUI loaded from an .ui file that require some sort of customization that is not a public function or cannot be easily "fixed" through an eventFilter are "promoted widgets".</div><div><br></div><div>The last point is probably the one that creates more confusion above everything else. But, while it might seem an annoying thing to do, once you've got the hand of it, it's fairly easy to implement a widget just by subclassing only what you need.<br><br>Let's assume you've a QMainWindow with a QListView for which you only need to print out drop events, and let's assume you'll use "myprogram.py" as the file for your python program.</div><div><br></div><div>- Create a QMainWindow in Designer with a list view, and ensure that the dragDropMode is set to DropOnly or DragDrop.</div><div>- Right click on the view and select "Promote to..."</div><div>- Type the class name, let's say "MyListView", and in the "Header file" field type "myprogram" (the name you'd use if you were to import the main python code file)</div><div>- Click "Add", then "Promote"</div><div>- save the ui file in the same directory the myprogram.py is</div><div>- And that's the only code you'll need, avoiding any eventFilter or whatsoever:</div><div><br></div><div><div><font face="monospace, monospace">class MyListView(QtWidgets.QListView):</font></div><div><font face="monospace, monospace">    def dragEnterEvent(self, event):</font></div><div><font face="monospace, monospace">        # to get a dropEvent, </font><span style="font-family:monospace,monospace">both the dragEnterEvent and</span></div><div><font face="monospace, monospace">        # dragMoveEvent (which is fired right after) have to </font></div><div><font face="monospace, monospace">        # be accepted!</font></div><div><font face="monospace, monospace">        event.accept()</font></div><div><font face="monospace, monospace">    def dragMoveEvent(self, event):</font></div><div><font face="monospace, monospace">        event.accept()</font></div><div><font face="monospace, monospace">    def dropEvent(self, event):</font></div><div><font face="monospace, monospace">        print('Something has been dropped in here!')</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">class Window(QtWidgets.QMainWindow):</font></div><div><font face="monospace, monospace">    def __init__(self):</font></div><div><font face="monospace, monospace">        QtWidgets.QWidget.__init__(self)</font></div><div><font face="monospace, monospace">        loadUi('mywindow.ui', self)</font></div></div><div><font face="monospace, monospace">        # the list view (and its properties/methods) is available as </font></div><div><font face="monospace, monospace">        # a direct attribute of the main class</font></div><div><font face="monospace, monospace">        self.listView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)</font></div><div><br></div><div><br></div><div>Still considering the small naming "drawbacks" and path issues listed before, this allows you to have some clean code, get simple and logical references to all widgets and still implement custom widgets in an easy way.<br>For example, you can add a QPushButton and implement its paintEvent only, or a QLabel and allow it to react to mousePressEvent by sending a custom signal.<br><br></div><div>A couple of considerations:</div><div>- Whenever you'll use a promoted widget, PyQt will "silently import" the file set as the "header"; if you've some processing in those files, they will be executed everytime an ui (and its promoted widget) is loaded.</div><div>- Paths: loadUi() doesn't behave according to the path of the running program, but from where it's loaded. I'm using cxFreeze to build Windows and MacOS binaries for some projects and I had to create my own loadUi function that builds and returns the ui object (I don't need the actual ui object, I could've ignored that, but that's not the point):<br><br></div><div><div><font face="monospace, monospace">def loadUi(uiPath, widget):</font></div><div><span style="font-family:monospace,monospace">    current = path.dirname(path.abspath(__file__))</span><br></div><div><font face="monospace, monospace">    #fix for cx_freeze</font></div><div><font face="monospace, monospace">    if current.endswith('\\library.zip\\myproject'):</font></div><div><font face="monospace, monospace">        current = current.replace('\\library.zip', '')</font></div><div><font face="monospace, monospace">    elif current.endswith('/library.zip/myproject'):</font></div><div><font face="monospace, monospace">        current = current.replace('/library.zip', '')</font></div><div><font face="monospace, monospace">    return uic.loadUi(path.join(current, uiPath), widget)</font></div></div><div><br></div><div>While you can ignore the ifs if you're not using similar building systems, the path relocation is necessary, since uic will try to load the file from the path the program is ran from, which is not good.</div><div><br>Hope this helps <img src="/groupoffice/views/Extjs3/themes/Default/images/emoticons/normal/smile.gif" alt=":-)"></div><div><br></div><div>Maurizio</div><div><br></div><div><br></div></div>-- <br><div dir="ltr" class="gmail_signature">È difficile avere una convinzione precisa quando si parla delle ragioni del cuore. - "Sostiene Pereira", Antonio Tabucchi<br><a target="_blank" class="blue" href="http://www.jidesk.net/">http://www.jidesk.net</a></div></div></div></div></div></div></div></div></div></div></div></div></div></div>
</blockquote></body></html>