python - PyQt4: Replace QWidget objects at runtime -


in application have replace qlineedit elements customized qlineedit. there different solutions:

  1. modify generated py file pyuic4 , replace there qlineedit objects 1 lineedit. solution not best, because every time run pyuic4 lose modification did generated output file.
  2. write new class search recursively inside window or dialog qlineedit widget types , replace them 1 lineedit. solution better. allows me same other objects or extend want without care dialog or window.

so far, write module (widgetreplacer) search recursively qgridlayout items , search if there qlineedit children. if yes, replace one.

the problem when try access 1 of lineedit objects following error:

runtimeerror: wrapped c/c++ object of type qlineedit has been deleted 

and if @ output notice modified qlineedit object has sitll old id:

old qt_obj <pyqt4.qtgui.qlineedit object @ 0x0543c930> replaced txt_line_1 lineedit new qt_obj <lineedit.lineedit object @ 0x0545b4b0> ---------------------------------- ... ---------------------------------- <pyqt4.qtgui.qlineedit object @ 0x0543c930> 

question

why happen this? how can replace qwidgets @ runtime?


update

here additional details regarding ojects wrapping: inside module widgetreplace if dump qeditline , lineedit objects get:

<pyqt4.qtgui.qlineedit object @ 0x05378618>     reference count: 7     address of wrapped object: 051fac40     created by: python     destroyed by: c/c++     parent wrapper: <pyqt4.qtgui.qgridlayout object @ 0x05378588>     next sibling wrapper: null     previous sibling wrapper: <pyqt4.qtgui.qlabel object @ 0x05378930>     first child wrapper: null 

and

<lineedit.lineedit object @ 0x05378978>     reference count: 3     address of wrapped object: 051fac40     created by: python     destroyed by: c/c++     parent wrapper: <__main__.dialog object @ 0x0535fbb8>     next sibling wrapper: <pyqt4.qtgui.qgridlayout object @ 0x05378780>     previous sibling wrapper: null     first child wrapper: null 

instead if dump line edit main, follow, represent deleted qlineedit object:

<pyqt4.qtgui.qlineedit object @ 0x05378618>     reference count: 2     address of wrapped object: 00000000     created by: python     destroyed by: c/c++     parent wrapper: null     next sibling wrapper: null     previous sibling wrapper: null     first child wrapper: null 

here code

dialog ui , generate file can dowloaded dropbox dialog.ui , dialog.py

main

import sys pyqt4.qtgui import qdialog, qapplication dialog import ui_form widgetreplacer import widgetreplacer  class dialog(qdialog, ui_form):      def __init__(self, parent = none):         super(dialog, self).__init__(parent)          # set user interface designer.         self.setupui(self)         widgetreplacer().replace_all_qlineedit(self)   if __name__ == "__main__":     app = qapplication(sys.argv)     window = dialog()      window.show()      print window.txt_line_1     window.txt_line_1.settext("hello text 1")      sys.exit(app.exec_()) 

lineedit

from pyqt4.qtgui import qlineedit, qvalidator, qpalette pyqt4 import qtcore  class lineedit(qlineedit):      def __init__(self, parent=none):         super(lineedit, self).__init__(parent)          self.color_red = qpalette()         self.color_red.setcolor(qpalette.text, qtcore.qt.red)          self.color_black = qpalette()         self.color_black.setcolor(qpalette.text, qtcore.qt.red)          # make connections         self.textchanged.connect(self.verify_text)      def verify_text(self, text):         validator = self.validator()         is_valid = qvalidator.acceptable          if validator not none:             is_valid = validator.validate(text, 0)          if is_valid == qvalidator.acceptable:             self.setpalette(self.color_black)         elif is_valid in [qvalidator.invalid, qvalidator.intermediate]:             self.setpalette(self.color_red) 

widgetreplacer

import sip lineedit import lineedit pyqt4.qtcore import qregexp pyqt4 import qtgui  class widgetreplacer():      def __init__(self):         pass      def replace_all_qlineedit(self, qt_dlg):         children = self._get_all_gridlayout(qt_dlg)          items = []         child in children:             new_items = self._find_all_obj_in_layout(child, qtgui.qlineedit)             items.extend(new_items)          item in items:             layout = item[0]             row = item[1]             column = item[2]             qt_obj = item[3]             self._replace_qlineedit_from_gridlayout(qt_dlg, qt_obj,                                                     layout, row, column)      def _get_all_gridlayout(self, qt_dlg):         return qt_dlg.findchildren(qtgui.qgridlayout, qregexp("gridlayout_[0-9]"))      def _find_all_obj_in_layout(self, layout, qt_type):         # output list format:         # layout, row, col, qt_obj,         objects = []         if type(layout) == qtgui.qgridlayout:             layout_cols = layout.columncount()             layout_rows = layout.rowcount()             in range(layout_rows):                 j in range(layout_cols):                     item = layout.itematposition(i, j) #                    print "item(",i, j, "):", item                      if type(item) == qtgui.qwidgetitem:                         if type(item.widget()) == qt_type:                             new_obj = [layout, i, j, item.widget()]                             objects.append(new_obj)          elif type(layout) in [qtgui.qhboxlayout, qtgui.qvboxlayout]:             raise syntaxerror("error: find of qt objects in qhboxlayout or qvboxlayout still not supported") #            in range(layout.count()): #                item = layout.itemat(i)          return objects      def _replace_qlineedit_from_gridlayout(self, parent, qt_obj, layout, row, column):         print "old qt_obj", qt_obj         obj_name = qt_obj.objectname()         layout.removewidget(qt_obj)         sip.delete(qt_obj)         qt_obj = lineedit(parent)         qt_obj.setobjectname(obj_name)          layout.addwidget(qt_obj, row, column)         print "replaced", obj_name, "with lineedit"          print "new qt_obj", qt_obj         print "----------------------------------" 

don't replace widgets @ runtime: promote widgets in qt designer line-edits automatically replaced custom class when gui module generated.

here's how promote widget use custom class:

in qt designer, select line-edits want replace, right-click them , select "promote to...". in dialog, set "promoted class name" "lineedit", , set "header file" python import path module contains class (e.g. myapp.lineedit). click "add", , "promote", , see class change "qlineedit" "lineedit" in object inspector pane.

now when re-generate ui module pyuic, should see uses custom lineedit class , there line @ bottom of file this:

    myapp.lineedit import lineedit 

Comments

Popular posts from this blog

java - WrongTypeOfReturnValue exception thrown when unit testing using mockito -

php - Magento - Deleted Base url key -

android - How to disable Button if EditText is empty ? -