2014-04-24 12 views
10

Prima di provare a scrivere le mie funzioni del modulo PyQt4 Python ... Volevo chiedere se qualcuno ha una funzione simile da condividere.Python PyQt4 funzioni per salvare e ripristinare i valori del widget UI?

In molti dei miei programmi python in cui ho una GUI creata utilizzando PyQt4 e qtDesigner, utilizzo il metodo QSettings per salvare e ripristinare gli stati dell'interfaccia utente e i valori di tutti i widget durante la chiusura e l'avvio.

Questo esempio mostra come salvare e ripristinare alcuni campi LineEdit, checkBox e radioButton.

Qualcuno ha una funzione che può attraversare l'interfaccia utente e trovare TUTTI i widget/controlli e i loro stati e salvarli (ad esempio guisave()) e un'altra funzione che può ripristinarli (ad esempio guirestore())?

mio CloseEvent simile a questa:

#--------------------------------------------- 
# close by x OR call to self.close 
#--------------------------------------------- 

def closeEvent(self, event):  # user clicked the x or pressed alt-F4... 

    UI_VERSION = 1 # increment this whenever the UI changes significantly 

    programname = os.path.basename(__file__) 
    programbase, ext = os.path.splitext(programname) # extract basename and ext from filename 
    settings = QtCore.QSettings("company", programbase)  
    settings.setValue("geometry", self.saveGeometry()) # save window geometry 
    settings.setValue("state", self.saveState(UI_VERSION)) # save settings (UI_VERSION is a constant you should increment when your UI changes significantly to prevent attempts to restore an invalid state.) 

    # save ui values, so they can be restored next time 
    settings.setValue("lineEditUser", self.lineEditUser.text()); 
    settings.setValue("lineEditPass", self.lineEditPass.text()); 

    settings.setValue("checkBoxReplace", self.checkBoxReplace.checkState()); 
    settings.setValue("checkBoxFirst", self.checkBoxFirst.checkState()); 

    settings.setValue("radioButton1", self.radioButton1.isChecked()); 

    sys.exit() # prevents second call 

mio MainWindow init simile a questa:

def __init__(self, parent = None): 
    # initialization of the superclass 
    super(QtDesignerMainWindow, self).__init__(parent) 
    # setup the GUI --> function generated by pyuic4 
    self.setupUi(self) 

    #--------------------------------------------- 
    # restore gui position and restore fields 
    #--------------------------------------------- 

    UI_VERSION = 1 

    settings = QtCore.QSettings("company", programbase) # http://pyqt.sourceforge.net/Docs/PyQt4/pyqt_qsettings.html 

    self.restoreGeometry(settings.value("geometry")) 
    self.restoreState(settings.value("state"),UI_VERSION) 

    self.lineEditUser.setText(str(settings.value("lineEditUser"))) # restore lineEditFile 
    self.lineEditPass.setText(str(settings.value("lineEditPass"))) # restore lineEditFile 

    if settings.value("checkBoxReplace") != None: 
     self.checkBoxReplace.setCheckState(settings.value("checkBoxReplace")) # restore checkbox 
    if settings.value("checkBoxFirst") != None: 
     self.checkBoxFirst.setCheckState(settings.value("checkBoxFirst")) # restore checkbox 

    value = settings.value("radioButton1").toBool() 
    self.ui.radioButton1.setChecked(value) 

risposta

16

OK, ho scritto un modulo con 2 funzioni per fare quello che mi è stato chiesto per. Non proprio complicato, una volta capito, ma sicuramente risparmia molto tempo ogni volta che crei nuovi programmi pyqt gui in cui vuoi salvare i valori del campo widget tra le sessioni. Attualmente sono codificati solo i campi lineEdit, checkBox e combobox. Se qualcun altro desidera aggiungere o migliorare (ad esempio i pulsanti di opzione ... ecc.) ... sono sicuro che gli altri, incluso me stesso, lo apprezzeranno.

#=================================================================== 
# Module with functions to save & restore qt widget values 
# Written by: Alan Lilly 
# Website: http://panofish.net 
#=================================================================== 

import sys 
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 
import inspect 

#=================================================================== 
# save "ui" controls and values to registry "setting" 
# currently only handles comboboxes editlines & checkboxes 
# ui = qmainwindow object 
# settings = qsettings object 
#=================================================================== 

def guisave(ui, settings): 

    #for child in ui.children(): # works like getmembers, but because it traverses the hierarachy, you would have to call guisave recursively to traverse down the tree 

    for name, obj in inspect.getmembers(ui): 
     #if type(obj) is QComboBox: # this works similar to isinstance, but missed some field... not sure why? 
     if isinstance(obj, QComboBox): 
      name = obj.objectName()  # get combobox name 
      index = obj.currentIndex() # get current index from combobox 
      text = obj.itemText(index) # get the text for current index 
      settings.setValue(name, text) # save combobox selection to registry 

     if isinstance(obj, QLineEdit): 
      name = obj.objectName() 
      value = obj.text() 
      settings.setValue(name, value) # save ui values, so they can be restored next time 

     if isinstance(obj, QCheckBox): 
      name = obj.objectName() 
      state = obj.checkState() 
      settings.setValue(name, state) 

#=================================================================== 
# restore "ui" controls with values stored in registry "settings" 
# currently only handles comboboxes, editlines &checkboxes 
# ui = QMainWindow object 
# settings = QSettings object 
#=================================================================== 

def guirestore(ui, settings): 

    for name, obj in inspect.getmembers(ui): 
     if isinstance(obj, QComboBox): 
      index = obj.currentIndex() # get current region from combobox 
      #text = obj.itemText(index) # get the text for new selected index 
      name = obj.objectName() 

      value = unicode(settings.value(name)) 

      if value == "": 
       continue 

      index = obj.findText(value) # get the corresponding index for specified string in combobox 

      if index == -1: # add to list if not found 
       obj.insertItems(0,[value]) 
       index = obj.findText(value) 
       obj.setCurrentIndex(index) 
      else: 
       obj.setCurrentIndex(index) # preselect a combobox value by index  

     if isinstance(obj, QLineEdit): 
      name = obj.objectName() 
      value = unicode(settings.value(name)) # get stored value from registry 
      obj.setText(value) # restore lineEditFile 

     if isinstance(obj, QCheckBox): 
      name = obj.objectName() 
      value = settings.value(name) # get stored value from registry 
      if value != None: 
       obj.setCheckState(value) # restore checkbox 

     #if isinstance(obj, QRadioButton):     

################################################################ 

if __name__ == "__main__": 

    # execute when run directly, but not when called as a module. 
    # therefore this section allows for testing this module! 

    #print "running directly, not as a module!" 

    sys.exit() 
+0

Molto poco utile modulo. Grazie! Funziona bene quando si salvano QSettings su un file ini, ad es. 'guisave (self.ui, QtCore.QSettings ('saved.ini', QtCore.QSettings.IniFormat))' che crea un file che può essere condiviso tra gli utenti. – Snorfalorpagus

+0

Ho dovuto modificare un paio di righe in 'value = unicode (settings.value (name) .toString())' come settings.value restituiva un QVariant. – Snorfalorpagus

+0

Raffinati miglioramenti Snorfalorpagus! Mi piace :) – panofish

5

Ecco un frammento di codice aggiornato che ha inizialmente condiviso da mr. Panofish. Quelle grandi funzioni sono le stesse, ma ora possono essere usate su versioni non di PyQt e Python con modifiche minori se necessario. Grazie. Panofish, lunga vita a OpenSource! :)

Modifiche:

  • Aggiornato per python3 e PyQt5
  • Aggiunto geometria Salva \ restore
  • Aggiunto QRadioButton salvare \ Restore
  • SetCheckState() replcaed con setChecked() al fine di evitare tristate

    def guisave(self): 
    
        # Save geometry 
        self.settings.setValue('size', self.size()) 
        self.settings.setValue('pos', self.pos()) 
    
        for name, obj in inspect.getmembers(ui): 
         # if type(obj) is QComboBox: # this works similar to isinstance, but missed some field... not sure why? 
         if isinstance(obj, QComboBox): 
          name = obj.objectName() # get combobox name 
          index = obj.currentIndex() # get current index from combobox 
          text = obj.itemText(index) # get the text for current index 
          settings.setValue(name, text) # save combobox selection to registry 
    
         if isinstance(obj, QLineEdit): 
          name = obj.objectName() 
          value = obj.text() 
          settings.setValue(name, value) # save ui values, so they can be restored next time 
    
         if isinstance(obj, QCheckBox): 
          name = obj.objectName() 
          state = obj.isChecked() 
          settings.setValue(name, state) 
    
         if isinstance(obj, QRadioButton): 
          name = obj.objectName() 
          value = obj.isChecked() # get stored value from registry 
          settings.setValue(name, value) 
    
    
    def guirestore(self): 
    
        # Restore geometry 
        self.resize(self.settings.value('size', QtCore.QSize(500, 500))) 
        self.move(self.settings.value('pos', QtCore.QPoint(60, 60))) 
    
        for name, obj in inspect.getmembers(ui): 
         if isinstance(obj, QComboBox): 
          index = obj.currentIndex() # get current region from combobox 
          # text = obj.itemText(index) # get the text for new selected index 
          name = obj.objectName() 
    
          value = (settings.value(name)) 
    
          if value == "": 
           continue 
    
          index = obj.findText(value) # get the corresponding index for specified string in combobox 
    
          if index == -1: # add to list if not found 
           obj.insertItems(0, [value]) 
           index = obj.findText(value) 
           obj.setCurrentIndex(index) 
          else: 
           obj.setCurrentIndex(index) # preselect a combobox value by index 
    
         if isinstance(obj, QLineEdit): 
          name = obj.objectName() 
          value = (settings.value(name).decode('utf-8')) # get stored value from registry 
          obj.setText(value) # restore lineEditFile 
    
         if isinstance(obj, QCheckBox): 
          name = obj.objectName() 
          value = settings.value(name) # get stored value from registry 
          if value != None: 
           obj.setChecked(strtobool(value)) # restore checkbox 
    
         if isinstance(obj, QRadioButton): 
         name = obj.objectName() 
         value = settings.value(name) # get stored value from registry 
         if value != None: 
          obj.setChecked(strtobool(value)) 
    
1

grazie Panofish e tutti sto aggiungendo qualche aggiornamento per QSlider/QSpinBox. è piccolo e semplice.

a guisave è possibile aggiungere:

if isinstance(obj, QSpinBox): 
    name = obj.objectName() 
    value = obj.value()    # get stored value from registry 
    settings.setValue(name, value) 

if isinstance(obj, QSlider): 
    name = obj.objectName() 
    value = obj.value()    # get stored value from registry 
    settings.setValue(name, value) 

a guirestore è possibile aggiungere:

if isinstance(obj, QSlider): 
    name = obj.objectName() 
    value = settings.value(name) # get stored value from registry 
    if value != None:   
     obj. setValue(int(value)) # restore value from registry 

if isinstance(obj, QSpinBox): 
    name = obj.objectName() 
    value = settings.value(name) # get stored value from registry 
    if value != None: 
     obj. setValue(int(value)) # restore value from registry 
0

Sto aggiungendo aggiornamento per QListWidget.

In guisave:

if isinstance(obj, QListWidget): 
    name = obj.objectName() 
    settings.beginWriteArray(name) 
    for i in range(obj.count()): 
     settings.setArrayIndex(i) 
     settings.setValue(name, obj.item(i).text()) 
    settings.endArray() 

in guirestore:

if isinstance(obj, QListWidget): 
    name = obj.objectName() 
    size = settings.beginReadArray(name) 
    for i in range(size): 
     settings.setArrayIndex(i) 
     value = settings.value(name) # get stored value from registry 
     if value != None: 
      obj.addItem(value) 
    settings.endArray()