pyqt5, looping over QtWidgets - python-3.x

I have created a dialog with qtdesigner. I wanted to modify certain widgets (e.g. buttons) programmatically.
I have my pyuic generated gui.py and have created a guiLogic.py defining the class "myGui".
class myGui(QtWidgets.QDialog, inmoovServoGui.Ui_Dialog):
The class init calls then the "setupUi" function from the generated gui.py
def __init__(self, *args, **kwargs):
QtWidgets.QDialog.__init__(self, *args, **kwargs)
self.setupUi(self)
...
In my python ide (pycharm) in the evaluate expression window I can type in now my class name followed by a . "myGui." and it will popup a list of all my QWidgets (beside others).
I have tried to get the same list but
myGui.__dict__.items()
does not contain the QWidgets. What am I doing wrong?

Related

How to combine multiple custom management commands in Django?

I wrote a set of commands for my Django project in the usual way. Is it possible to combine multiple commands into one command?
class Command(BaseCommand):
""" import all files in media in dir and add to db
after call process to generate thumbnails """
def handle(self, *args, **options):
...
To make easy steps I have commands like: import files, read metadata from files, create thumbnails etc. The goal now is to create a "do all" command that somehow imports these commands and executes them one after another.
How to do that?
You can define a DoAll command and use django django.core.management.call_command to run all your subcommands. Try something like below:
class FoobarCommand(BaseCommand):
""" call foo and bar commands """
def handle(self, *args, **options):
call_command("foo_command", *args, **options)
call_command("bar_command", *args, **options)

PyQT5 How do I change windows across files? [duplicate]

I'm using Qt Designer for design GUI to use in python, after designing my desired UI in Qt Designer, convert it to python code and then I changed generated code to do some action in my python code, but if I changed the UI with Qt Designer and convert it to python code again, I lost my previous changes on my code.
how can I solve the problem?
can we Spreading a Class Over Multiple Files in python to write code in other files?
To avoid having these problems it is advisable not to modify this file but to create a new file where we implement a class that uses that design.
For example, suppose you have used the MainWindow template in the design.ui file, then convert it to Ui_Design.py like to the following structure:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
[...]
def retranslateUi(self, MainWindow):
[...]
Then we will create a new file that we will call logic.py where we will create the file that handles the logic and that uses the previous design:
class Logic(QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
QMainWindow.__init__(self, *args, **kwargs)
self.setupUi(self)
So even if you modify the design and generate the file again .py you will not have to modify the file of the logic.
To generalize the idea we must have the following rules but for this the logic class must have the following structure:
class Logic(PyQtClass, DesignClass):
def __init__(self, *args, **kwargs):
PyQtClass.__init__(self, *args, **kwargs)
self.setupUi(self)
PyQtClass: This class depends on the design chosen.
Template PyQtClass
─────────────────────────────────────────────
Main Window QMainWindow
Widget QWidget
Dialog with Buttons Bottom QDialog
Dialog with Buttons Right QDialog
Dialog with Without Buttons QDialog
DesignClass: The name of the class that appears in your design.
The advantage of this implementation is that you can implement all the logic since it is a widget, for example we will implement the solution closing pyqt messageBox with closeevent of the parent window :
class Logic(QMainWindow, Ui_MainWindow):
def __init__(self, *args, **kwargs):
QMainWindow.__init__(self, *args, **kwargs)
self.setupUi(self)
def closeEvent(self, event):
answer = QtWidgets.QMessageBox.question(
self,
'Are you sure you want to quit ?',
'Task is in progress !',
QtWidgets.QMessageBox.Yes,
QtWidgets.QMessageBox.No)
if answer == QtWidgets.QMessageBox.Yes:
event.accept()
else:
event.ignore()
The easiest way is to use the *.ui file directly in the python code, you don't need convert to *.py file every time you change the ui.
you can use this pseudo code in your project.
# imports
from PyQt5 import uic
# load ui file
baseUIClass, baseUIWidget = uic.loadUiType("MainGui.ui")
# use loaded ui file in the logic class
class Logic(baseUIWidget, baseUIClass):
def __init__(self, parent=None):
super(Logic, self).__init__(parent)
self.setupUi(self)
.
.
.
.
def main():
app = QtWidgets.QApplication(sys.argv)
ui = Logic(None)
ui.showMaximized()
sys.exit(app.exec_())

importing dynamically generated class definitions from a dynamically generated dictionary inside __init__.py namespace

I have a Class Factory that generates classes with dynamic name assignment
I like to be able to access them from other modules which import a package A
currently I am loading the classes into a dictionary and updating the vars() of the init.py which to me seems not like a good idea, is there a better way of doing it?
class Model_Factory:
def __init__(self,list_of_names:list):
self._models={}
for name in list_of_names:
self.models[name]=Model_Factory.create_model(name)
#property
def models(self):
return self._models
#classmethod
def create_model(cls,cls_name):
def __init__(self, **kwargs):
super(type(self),self).__init__( **kwargs)
pass
return type(snake_case(cls_name), (parent),
{'__init__': __init__,
'aomething' : 'something',
'attribute_name':'value'})
then inside the package A's init.py
import whatever
some line of code
dic=Model_Factory().models
vars().update(dic)
Then when I want to access those classes all I have to do is to
from A import Dynamically_Created_Class_Name
This works perfectly fine and the other modules who need to import those classes know the dynamic names themselves alright, however this just does not seem to me the correct way of doing it, is there a method or built in method that would add class definition or a dictionary into the current module namespace?

pyqt5 how to code call the converted .py file rather than .ui file

I have an application where I can create the layout in pyqt designer which will make a .ui file. I also have a gui script that when running uses this .ui file.
I have been able to convert the .ui file into a .py file however I would like to have my code call the converted .py file.
summary:
main.ui file which is generated from pyqt designer
main.py file which is generated from main.ui
gui.py which uses main.ui as shown in code snip below
how could I make gui.py use main.py and not main.ui?
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.ui = uic.loadUi('main.ui', self)
Generated code consists of helper class, just import it, instantiate and call setupUi in __init__
from main import Ui_MainWindow
class MainWindow(QtWidgets.QMainWindow)
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
ui = Ui_MainWindow()
ui.setupUi(self)
self.ui = ui

Subclassing of Widgets which are loaded by uic.loadUi

I use python 3.6 and pyqt5 and load my Window by self.ui = uic.loadUi("MainWindow.ui",self) Mainly there are 2 QtreeViews and one QList Widgets. I've problems with dropEvent. I have to separate it to each Widget/model so that I have different 'dropActions'. But everytime I drop I get a call from the dropEvent Function of the self.ui Object I've tried to change self.ui.treeView.viewport().installEventFilter(self) to seperate functions without success. In the docs and in some examples found here and over the net there are the Widgets subclassed with the drag and drop functions. But I find no solution for Widgets generated by the uic loader. I've tried to install drag&drop functions inside the models. But no luck at all.
How can I subclass a Widget which is loaded by uic.loadUi?
or
How to create rules from where to where drag & drop is allowed ?
The easiest way is to do your subclassing beforehand.
Create my_tree_view.py as follows
from PyQt5 import QtWidgets, QtGui
class MyTreeView(QtWidgets.QTreeView):
def __init__(self, parent=None):
super().__init__(parent)
def dropEvent(self, event: QtGui.QDropEvent):
print('MyTreeView dropEvent')
super().dropEvent(event)
Then edit your .ui file and add the following near the end after the </widget> line.
<customwidgets>
<customwidget>
<class>MyTreeView</class>
<extends>QTreeView</extends>
<header>my_tree_view</header>
</customwidget>
</customwidgets>
And then change the following line (further up in your .ui file)
from
<widget class="QTreeView" name="treeView">
to
<widget class="MyTreeView" name="treeView">

Resources