2

I have a QPixmap within a QLabel that is changed based on a QComboBox selection. For example, the combobox may have a selection of fruits (e.g., 'apple', 'orange', 'banana'). If I choose 'apple' an image of an apple is displayed in the QLabel. I further want the image of the apple to change to a "special" image of an apple depending on whether a QRadioButton is toggled. Once I de-toggle the radio button the image should revert to the standard apple image. Currently I have it partially functional: if the radio button is toggled 'on' prior to selecting the combobox option, the image is displayed as desired; if, however, I toggle the radio button 'on' after selecting the combobox option only the standard image is displayed. Similarly, if I have the special image displayed and de-toggle the radio button, the image does not revert to the standard image.

I assume this has something to do with the "toggled()" method, but not sure how to implement it.

self.fruit_list = ['apple', 'orange', 'banana']

self.fruit_combo = QtGui.QComboBox()
self.fruit_combo.addItems(self.fruit_list)

self.btn = QtGui.QRadioButton("btn")

self.fruit_image = QtGui.QLabel(self)
self.grid.addWidget(self.fruit_image, 1, 1) 
self.fruit_combo.currentIndexChanged[str].connect(lambda: 
                  self.image_update(self.fruit_combo, self.fruit_image, self.btn)

def image_update(self, qcombobox, qlabel, btn):
    image_path ="c :/images"
    current_item = str(qcombobox.currentText())
    if btn.isChecked():
       current_image = '%s/%s_special.jpg' %(image_path, current_item)
    else:
       current_image = '%s/%s.jpg' %(image_path, current_item)
    qlabel.setPixmap(QtGui.QPixmap(current_image))

Thanks

zachn
  • 35
  • 3

1 Answers1

1

@zachn, you are correct, the problem is concerning toggled- more specific, it is the toggled signal that you need to connect to: http://doc.qt.io/qt-5/qabstractbutton.html#toggled

Try doing this:

import partial
self.btn.toggled.connect(partial (self.image_update, self.fruit_combo, self.fruit_lbl, self.btn))

EDIT: for @furas, here is some sample code, where I did not use images, only text to show changes in the QLabel. Note that I kept the method name image_update() even though it should be text_update(). (I coded this in Qt5, if used in Qt4 replace QtWidgets with QtGui)

class SomeFrame(object):
    def __init__(self):
        # Assets
        fruit_list = ['apple', 'orange', 'banana']

        # Creating content 
        self.frame = QtWidgets.QFrame()
        self.fruit_combo = QtWidgets.QComboBox()
        self.fruit_combo.addItems(fruit_list)
        self.btn = QtWidgets.QRadioButton("btn")

        self.fruit_lbl = QtWidgets.QLabel()

        # Creating Layout
        layout = QtWidgets.QHBoxLayout()
        layout.addWidget(self.fruit_lbl)
        layout.addWidget(self.btn)
        layout.addWidget(self.fruit_combo)
        self.frame.setLayout(layout)

        # Initialize text in fruit_lbl
        self.image_update(self.fruit_combo, self.fruit_lbl, self.btn)
        self.frame.show()

        # Connections
        self.fruit_combo.currentIndexChanged[str].connect(lambda: self.image_update(self.fruit_combo, self.fruit_lbl, self.btn))
        self.btn.toggled.connect(partial (self.image_update, self.fruit_combo, self.fruit_lbl, self.btn))

    def image_update(self, qcombobox, qlabel, btn):
        current_item = str(qcombobox.currentText())
        if btn.isChecked():
            new_text = 'CHECKED: %s' % current_item
        else:
            new_text = 'UNCHECKED: %s' % current_item
        qlabel.setText(new_text)

if __name__ == "__main__":
    from PyQt5 import QtWidgets
    import sys
    from functools import partial

    app = QtWidgets.QApplication(sys.argv)         
    theFrame = SomeFrame()
    sys.exit(app.exec_())
camelBack
  • 748
  • 2
  • 11
  • 30
  • OK, I am a little confused with partial cause I have not used them before and only seen the "power" examples. – zachn Jan 26 '17 at 15:38
  • It seems you are calling the image_update() twice, once through the combobox connection and the other through the radio button connect. – zachn Jan 26 '17 at 15:46
  • 1
    @zachn in this part of code `partial` works similar to `lambda` – furas Jan 26 '17 at 16:26
  • 1
    @zachn - it is correct to call `image_update()` twice. This function checks both widgets and then it updates image/label. – furas Jan 26 '17 at 16:34
  • 1
    Is using partial necessary here to improve readability, etc. or is its usage trivial? – zachn Jan 26 '17 at 18:30
  • 1
    @zachn: In general, I like using partial vs. lambda while connecting signals to methods. I think it is more readable in that way. There are other differences that you can read about: 1) [late/early binding](http://code.saghul.net/index.php/2010/11/20/lambda-vs-functools-partial/) 2) [Execution/performance](http://stackoverflow.com/questions/11828410/differences-between-functools-partial-and-a-similar-lambda) – camelBack Jan 26 '17 at 20:33