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_())
Related
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
I've made my first small GUI program using PyQt5 for some data process for my work.
I have a problem - I can't make QFileDialog (to open file) with the focus on its QListView widget. (In QFileDialog class by default focus is on QLineEdit).
The best solution is to make new class from QFileDialog with changed setFocus settings and unchanged all the other.
It turned out to be not so easy because I didn't find how to adress to inner widgets of QFileDialog.
I'm new in PyQt5, couldn't find any solutionts even for Qt C++.
Thank you for any advices and ideas.
class XFileDialog(QtWidgets.QFileDialog):
"magic code"
file=XFileDialog.getOpenFileName(caption="Open",
filter="FITS (*.fits *.fts *.new)")
It seems that I have found the solution. Perhaps it could be useful for someone.
class XFileDialog(QtWidgets.QFileDialog):
def __init__(self):
QtWidgets.QFileDialog.__init__(self)
self.setDirectory(progdir)
def setVisible(self,v):
super(XFileDialog, self).setVisible(v)
self.setAcceptMode(0)
self.setFileMode(1)
self.setFocusPolicy(11)
self.setNameFilter("All (*) ;; FITS (*.fts *.fits *.new)")
self.focusPreviousChild()
class MyWindow(QtWidgets.QWidget):
def __init__(self,parent=None):
QtWidgets.QWidget.__init__(self,parent)
super().__init__()
self.initUI()
def openFile(self):
global progdir
progdir=QtCore.QDir(os.getcwd())
file=XFileDialog()
file.exec()
.......
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?
I have created a GUI (using wxPython) that allows the user to search for files and their content. The program consists of three parts:
The main GUI window
The searching mechanism (seperate class)
The output window that displays the results of the file search (seperate class)
Currently I'm using pythons threading module to run the searching mechanism (2) in a separate thread, so that the main GUI can still work flawlessly. I'm passing the results during runtime to the output window (3) using Queue. This works fine for less performance requiring file-reading-actions, but as soon as the searching mechanism requires more performance, the main GUI window (1) starts lagging.
This is roughly the schematic:
import threading
import os
import wx
class MainWindow(wx.Frame): # this is point (1)
def __init__(self, parent, ...):
# Initialize frame and panels etc.
self.button_search = wx.Button(self, label="Search")
self.button_search.Bind(wx.EVT_BUTTON, self.onSearch)
def onSearch(self, event):
"""Run filesearch in separate Thread""" # Here is the kernel of my question
filesearch = FileSearch().Run()
searcher = threading.Thread(target=filesearch, args=(args,))
searcher.start()
class FileSearch(): # this is point (2)
def __init__(self):
...
def Run(self, args):
"""Performs file search"""
for root, dirs, files in os.walk(...):
for file in files:
...
def DetectEncoding(self):
"""Detects encoding of file for reading"""
...
class OutputWindow(wx.Frame): # this is point (3)
def __init__(self, parent, ...):
# Initialize output window
...
def AppendItem(self, data):
"""Appends a fileitem to the list"""
...
My questions:
Is python's multiprocessing module better suited for this specific performance requiring job?
If yes, which way of interprocess communication (IPC) should I choose to send the results from the searching mechanism class (2) to the output window (3) and how should implement it schematically?
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">