3

I made an list (array) that would count number of game finish. But if someone restarted game, length of list would reset.

As I know QSettings is dedicated to save and store data. I have read documentation but didn't help me enough.

For example I have a global array:

global finishcount
finishcount = []

How can I apply this to QSettings? So then I can append data on it without data loss after restart.

Should it look something like this?

from PyQt4 import QtGui, QtCore
global finishcount
finishcount = []
settings = QtCore.QSettings(self)
settings.setValue(finishcount, self)

How can I achieve this? Or can I make list in QSettings itself where I can append something?

Mel
  • 5,837
  • 10
  • 37
  • 42
ShellRox
  • 2,532
  • 6
  • 42
  • 90

2 Answers2

2

Below is a very simple demo that shows how to read and write a list of integers to QSettings. The demo automatically adds a new value every time the window is opened and closed.

If you're using PyQt, there is no need to use json at all. For lists, just provide a default, and specify the type of the contained values:

    settings.value('finishcount', [], int)

Demo:

from PyQt4 import QtCore, QtGui

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        settings = QtCore.QSettings('my_org', 'my_app')
        self._finishcount = settings.value('finishcount', [], int)
        print('read settings: %s' % self._finishcount)
        # add a new value for testing
        self._finishcount.append(len(self._finishcount))

    def closeEvent(self, event):
        settings = QtCore.QSettings('my_org', 'my_app')
        settings.setValue('finishcount', self._finishcount)
        print('save settings: %s' % self._finishcount)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 100, 100, 100)
    window.show()
    sys.exit(app.exec_())

NB: for the special case of a list of strings, it's best to use this:

    settings.value('finishcount', [], 'QStringList')

rather than specifying the type with str. Otherwise, empty lists don't get treated properly.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • I found that after setting `settings.setValue('mykey',[])`, on the NEXT load of the program `settings.value('mykey', [], str)` gives `''` instead of `[]`. Is it to be expected? – Jason Feb 19 '19 at 07:10
  • @Jason Yeah, I think this is a bit of a wart. You can work around it by doing: `settings.value('mykey', [], 'QStringList')`. – ekhumoro Feb 19 '19 at 22:10
1

Generally it looks something like this. This also assumes your using the v2 version of the QVariant api; otherwise, the results returned from QSettings.value is going to be a QVariant and you'll need to cast it to the appropriate python type. If you're using a recent version of PyQt then you should be on v2, but if not you can force it by sticking this at the top of your file

import sip
sip.setapi('QVariant', 2)
sip.setapi('QString', 2)

Also, even with the v2 version of the api, it often doesn't always work as expected with anything more complicated than strings or numbers. For more complex types like lists and dicts, I've found it's often better to serialize the values using json or pickle and save that to the QSettings instead, and then unserialize it myself when retrieving it.

import json

class MyWidget(QWidget):

    def __init__(self, parent):
        super(MyWidget, self).__init__(parent)
        self.myvalue = 10
        self.mylist = [1,2,3]
        self.restoreSettings()

    def closeEvent(self, event):
        self.saveSettings()
        super(MyWidget, self).closeEvent(event)

    def saveSettings(self):
        settings = QSettings('myorg', 'myapp')
        settings.setValue('myvalue', self.myvalue)
        settings.setValue('mylist', json.dumps(self.mylist))

    def restoreSettings(self):
        settings = QSettings('myorg', 'myapp')
        self.myvalue = settings.value('myvalue', self.myvalue)
        try:
            self.mylist = json.loads(settings.value('mylist', None))
        except (ValueError, TypeError):
            pass
Community
  • 1
  • 1
Brendan Abel
  • 35,343
  • 14
  • 88
  • 118
  • Can you give a specific example of a `list` or `dict` that doesn't work as expected? Given the fact that `json` only supports a limited range of types, it would be a bug if they couldn't also be serialized by `QSettings`. – ekhumoro May 06 '16 at 23:55
  • Admittedly, I'm using PySide -- but `[1,2,3]` is returned as `[u'1', u'2', u'3']` from `QSettings` – Brendan Abel May 07 '16 at 00:37
  • Ah. PyQt has added an argument that allows you to specify the type. So `settings.value('mylist', type=int)` will return the right thing. Don't think PySide supports that, but you can work around the issue by putting the list inside a `tuple`. Or, more generally, just force Qt to write a `@Variant` entry, rather than a string-list. – ekhumoro May 07 '16 at 02:37
  • I don't quite understand second code, Do i need to make a json file where i will have my lists? if so, how can i achieve that since i am not familiar with json files. – ShellRox May 07 '16 at 06:05
  • It's basically just converting your list to a string before it saves it. And then it converts it from a string back into a list when it reads it. – Brendan Abel May 07 '16 at 06:10