Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing a preferences dialog window in PyQt

I'm trying to use an interface I designed in Qt designer as a means of letting the user edit preferences for my program.

I am currently able to display the GUI I made by connecting the following function to the preferences menu option:

def preferences(self):

    preferences_dialog = QtGui.QDialog()
    preferences_dialog.ui = Ui_Preferences()
    preferences_dialog.ui.setupUi(preferences_dialog)
    preferences_dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
    preferences_dialog.exec_()

My question is this: what is a good way to implement this so that I can use the fields in the GUI to change values in my config file?

I also want to display the pre-existing values in the boxes before they are changed.

Should I make a new class that uses the above function as its __init__ method? I would imagine I might need a class that handles all of the processes for the window. Also, I am unsure of a good way to pass data between the file and the GUI without a bunch of specific code.

enter image description here

like image 646
Matthew H Thiess Avatar asked Dec 25 '22 02:12

Matthew H Thiess


1 Answers

Use QSettings. Here's an example in PyQt5.

First, the main window's ui definition

# file ui_main.py
from PyQt5 import QtCore, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(584, 897)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 584, 21))
        self.menubar.setObjectName("menubar")
        self.menuPreferences = QtWidgets.QMenu(self.menubar)
        self.menuPreferences.setObjectName("menuPreferences")
        MainWindow.setMenuBar(self.menubar)
        self.setPreferencesAction = QtWidgets.QAction(MainWindow)
        self.setPreferencesAction.setObjectName("setPreferencesAction")
        self.menuPreferences.addAction(self.setPreferencesAction)
        self.menubar.addAction(self.menuPreferences.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.menuPreferences.setTitle(_translate("MainWindow", "Settings"))
        self.setPreferencesAction.setText(_translate("MainWindow", "Preferences"))

and second, the preferences dialog ui definition:

# file ui_dialog.py
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(508, 300)
        self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
        self.buttonBox.setGeometry(QtCore.QRect(150, 250, 341, 32))
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.buttonBox.setObjectName("buttonBox")
        self.sl_value = QtWidgets.QSlider(Dialog)
        self.sl_value.setGeometry(QtCore.QRect(220, 120, 161, 31))
        self.sl_value.setOrientation(QtCore.Qt.Horizontal)
        self.sl_value.setObjectName("sl_value")
        self.buttonBox.accepted.connect(Dialog.accept)
        self.buttonBox.rejected.connect(Dialog.reject)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

The MainWindow keeps track of the configuration in a QSettings object, which is uniquely defined (and accessed) using the application and company strings fed into its constructor.

# file main.py
class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.settings = QSettings(COMPANY_NAME, APPLICATION_NAME)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

when the preferences dialog box is triggered, the settings are loaded and passed along to the PreferencesDialog. If the Dialog returns successfully, the new settings are saved and written to storage using del

    @pyqtSlot(bool)
    def on_setPreferencesAction_triggered(self, triggered):
        settings = self.settings
        default_config_value = settings.value(CONFIG_KEY_1, defaultValue=None, type=str)

        preference_dialog = PreferencesDialog(default_config_value=default_config_value, parent=self)
        if preference_dialog.exec():
            settings.setValue(CONFIG_KEY_1, preference_dialog.preferences[CONFIG_KEY_1])

            # this writes the settings to storage
            del settings

The PreferencesDialog constructor sets the values according to the parameters it receives, and a a pyqtSlot is attached to the appropriate signal to save the values in a dictionary.

To run the demo:

if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
like image 72
Crispin Avatar answered Dec 31 '22 12:12

Crispin