问题
How to have all attributes and Qt views of an object updated when reloading the python module that defines this object, without breaking or even touching the links between this object and other objects?
Here is an exemple: The QMainWindow of a Qt application includes both local widgets and a reloadable widget:
from PyQt4 import QtCore, QtGui
import reloadable
name='Test reloadable'
class MyWindow(QtGui.QMainWindow):
def __init__(self):
# Initialize the main window
super(MyWindow, self).__init__()
self.setWindowTitle(name)
# Create an instance of the reloadable widget
self.reloadableWidget= reloadable.ReloadabelWidget()
# Create a local widget that can ask for and display an attribute of the reloadable widget
button1 = QtGui.QPushButton('Identify')
button1.clicked.connect(self.identifyReloadable)
self.label1=QtGui.QLabel('')
layout1 = QtGui.QHBoxLayout()
layout1.addWidget(button1)
layout1.addWidget(self.label1)
localWidget=QtGui.QWidget()
localWidget.setLayout(layout1)
# Put the local widget and the reloadable widget in the window
centralWidget=QtGui.QWidget()
layout = QtGui.QVBoxLayout()
layout.addWidget(localWidget)
layout.addWidget(self.reloadableWidget)
centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
def identifyReloadable(self):
identity=self.reloadableWidget.identify()
self.label1.setText(identity)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName(name)
main = MyWindow()
main.show()
sys.exit(app.exec_())
This reloadable widget (QFrame) has a method 'identify()' called by main and a method 'reload()' called by itself. This reload method essentially reloads the class module, replace the class attribute by the possibly updated module.class, and tries to update the Qt views of the object.
# This is module reloadble.py
from PyQt4 import QtCore, QtGui
import inspect
identity='1'
color='blue'
class ReloadabelWidget(QtGui.QFrame,object):
def __init__(self):
QtGui.QFrame.__init__(self)
self.setFrameStyle(1)
self.reinit()
def reinit(self):
button = QtGui.QPushButton('Reload',self)
button.clicked.connect(self.reload)
label=QtGui.QLabel(identity)
label.setStyleSheet("QLabel { background-color : white; color : %s; }" % color);
layout = QtGui.QHBoxLayout()
layout.addWidget(button)
layout.addWidget(label)
self.setLayout(layout)
self.setUpdatesEnabled(True)
def identify(self):
return identity # will change each time the file is edited with a new identity in line 3
def reload(self):
module=inspect.getmodule(self)
reload(module)
self.reinit() # object is reinitialized
self.__class__= module.ReloadabelWidget # callable attributes are now up to date
self.update() # naive attempt to update the Qt view => does not work
# add code here to have the GUI part of self, i.e. the QFrame updated ...
# ... whereever it is displayed.
The main application is running and the programmer redefines the method identify() and the color of a label by editing and saving the code of the reloadable module.
identity='2'
color='red'
The reload button is then clicked to run the reload() method of the reloadable widget. Its methods are properly updated and clicking the identify button displays the updated identity 2. But the widget's view is not updated because I don't know how to do it. What are the lines to be added at the end of the reload method to obtain the redisplay of the new interface, created by self.reinit()
?
PS1: For those who like to know what is the goal behind a question, I want to accelerate the development of a complicated multi-module application by having both the attributes and the gui of a module updated at code edition, without restarting the application.
PS2: This question replaces a bad one that I had asked without being sufficiently explicit. Since there was already several answers, I make this new post. I now provide a complete code entirely tested and make my point clearly.
来源:https://stackoverflow.com/questions/31492004/updating-a-qt-object-when-reloading-a-module-that-defines-a-class-subclassing-th