Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get previous and newly selected item on activation in QComboBox

In my program some comboboxes (QComboBox) were used to make several settings. Sometimes its necessary not only to know the item the user selected but also the item which was selected previously in the combobox. Well, transferring the new selection is quite easy:

self.MyCombobox.activated[str].connect(self.ComboChange)

But how do i manage to not only passing the newly selected but also the previous item to a function when the index changed?

My compromise solution would be to manually set a variable for every combobox which stores the last selected value so that it can be accessed when the selction has changed. But considering that i have a lot of Comboboxes this would be quite prone to errors until some boxes could be updated on different ways.

Thanks in advance for your help

A minimal working example:

import sys

from PyQt5.QtWidgets import (   QApplication, QWidget, QGridLayout, QComboBox,
                                QLabel)

class BaseWidget(QWidget):
    def __init__(self):
        super(BaseWidget, self).__init__()
        self.setGeometry(300, 300, 300, 200)

        # 2 Labels to display the new and the old item after selection
        self.LabelOldItem = QLabel(self)
        self.LabelNewItem = QLabel(self)

        self.MyCombobox = QComboBox(self)
        self.MyCombobox.addItems(['Item 1', 'Item 2', 'Item 3', 'Item 4'])
        self.MyCombobox.activated[str].connect(self.ComboChange)


        grid = QGridLayout()
        grid.addWidget(self.MyCombobox, 0, 0, 1, 1)
        grid.addWidget(self.LabelOldItem, 1, 0, 1, 1)
        grid.addWidget(self.LabelNewItem, 2, 0, 1, 1)

        self.setLayout(grid)

    def ComboChange(self, newitem):
        self.LabelOldItem.setText('Previous Selection: ') # <- crucial point
        # How can i transfer both, not only the new item but also the previous
        # item of the combobox when it gets activated?
        self.LabelNewItem.setText('New Selection: <b>' + newitem + '</b>')


if __name__ == '__main__':

    app = QApplication(sys.argv)

    pyqtComboExample = BaseWidget()
    pyqtComboExample.show()
    sys.exit(app.exec_())

Minimal working example

like image 894
Bastian Avatar asked Sep 11 '18 07:09

Bastian


1 Answers

A possible solution is to create a custom QComboBox:

import sys
from PyQt5 import QtCore, QtWidgets


class ComboBox(QtWidgets.QComboBox):
    new_signal = QtCore.pyqtSignal(str, str)

    def __init__(self, parent=None):
        super(ComboBox, self).__init__(parent)
        self.lastSelected = ""
        self.activated[str].connect(self.onActivated)

    def onActivated(self, text):
        self.new_signal.emit(self.lastSelected, text)
        self.lastSelected = text


class BaseWidget(QtWidgets.QWidget):
    def __init__(self):
        super(BaseWidget, self).__init__()
        self.setGeometry(300, 300, 300, 200)

        # 2 Labels to display the new and the old item after selection
        self.LabelOldItem = QtWidgets.QLabel()
        self.LabelNewItem = QtWidgets.QLabel()

        self.MyCombobox = ComboBox()
        self.MyCombobox.addItems(['Item 1', 'Item 2', 'Item 3', 'Item 4'])
        self.MyCombobox.new_signal.connect(self.ComboChange)

        grid = QtWidgets.QGridLayout(self)
        grid.addWidget(self.MyCombobox, 0, 0, 1, 1)
        grid.addWidget(self.LabelOldItem, 1, 0, 1, 1)
        grid.addWidget(self.LabelNewItem, 2, 0, 1, 1)

    def ComboChange(self, lastitem, newitem):
        self.LabelOldItem.setText('Previous Selection: <b>{}</b>'.format(lastitem))
        self.LabelNewItem.setText('New Selection: <b>{}</b>'.format(newitem))


if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    pyqtComboExample = BaseWidget()
    pyqtComboExample.show()
    sys.exit(app.exec_())

Another possible solution is to use sender() to get the QComboBox used, and save the old item in a property:

import sys
from PyQt5 import QtCore, QtWidgets


class BaseWidget(QtWidgets.QWidget):
    def __init__(self):
        super(BaseWidget, self).__init__()
        self.setGeometry(300, 300, 300, 200)

        # 2 Labels to display the new and the old item after selection
        self.LabelOldItem = QtWidgets.QLabel()
        self.LabelNewItem = QtWidgets.QLabel()

        self.MyCombobox = QtWidgets.QComboBox()
        self.MyCombobox.addItems(['Item 1', 'Item 2', 'Item 3', 'Item 4'])
        self.MyCombobox.activated[str].connect(self.ComboChange)

        grid = QtWidgets.QGridLayout(self)
        grid.addWidget(self.MyCombobox, 0, 0, 1, 1)
        grid.addWidget(self.LabelOldItem, 1, 0, 1, 1)
        grid.addWidget(self.LabelNewItem, 2, 0, 1, 1)

    def ComboChange(self, newitem):
        combo = self.sender()
        lastitem = combo.property("lastitem")
        self.LabelOldItem.setText('Previous Selection: <b>{}</b>'.format(lastitem))
        self.LabelNewItem.setText('New Selection: <b>{}</b>'.format(newitem))
        combo.setProperty("lastitem", newitem)


if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    pyqtComboExample = BaseWidget()
    pyqtComboExample.show()
    sys.exit(app.exec_())
like image 102
eyllanesc Avatar answered Oct 01 '22 14:10

eyllanesc