1

Once an item is selected on a combo, it should get removed from the others, unless it's "No use".

I made three options of QComboBox, and each of those contains the same items.

The explanation is this:

  • QCombobox Tug 1 has total 4 items ('No Use', '207HR', '306DR', 'Jupiter')

  • QCombobox Tug 2 has total 4 items ('No Use', '207HR', '306DR', 'Jupiter')

  • QCombobox Tug 3 has total 4 items ('No Use', '207HR', '306DR', 'Jupiter')

The default value of those Qcombobox is 'No Use'.

How can I remove the selected value of QComboBox Tug 1 from QComboBox Tug 2?

The point is that 'No Use' shall not be removed; only an item from among '207HR', '306DR', and 'Jupiter'.

The Code i made is below:

class Ship_Use_Tug_Input_Program(QWidget):
    def __init__(self, master):
        super().__init__()
        self.initUI()

    def initUI(self):
        tug1_cb = QComboBox(self)
        jeju_tug = ['No use','207HR (2,500HP)', '306DR (3,600HP)', 'Jupiter (3,600HP)']
        tug1_cb.addItems(jeju_tug)

        tug2_cb = QComboBox(self)
        tug2_cb.addItems(jeju_tug)

        tug3_cb = QComboBox(self)
        tug3_cb.addItems(jeju_tug)

        self.setGeometry(100,100,1000,500) 
        self.setWindowTitle('Ship_Use_Tug_Input_Program')
        self.show()
app = QApplication(sys.argv)
exc = Ship_Use_Tug_Input_Program(master=Ship_Use_Tug_Input_Program)
app.exec_()

The explanation photo is below: enter image description here

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Woody Kim
  • 29
  • 8
  • Don't post the same question multiple times as that is annoying – eyllanesc Feb 07 '21 at 13:41
  • sorry, i did because i would like to specify the point of my question. i have already removed the previous question as your suggestion – Woody Kim Feb 07 '21 at 13:54
  • 1
    You already have several posts in SO so you should already know the rules: If you want to improve a question then just edit it. If you don't know the rules then check [ask] and pass the [tour] so that you don't continue causing annoyances, then don't complain that the system blocks the ability to create new posts – eyllanesc Feb 07 '21 at 13:56

1 Answers1

2

The view-widget of the combo-box can be used to hide the rows, and the item-data can be used to keep track of which combo-box is showing which row. A slot connected to the activated signal can then update the items whenever one of the current-items change.

Below is a complete demo script that implements that. The ExclusiveComboGroup class can be used with any group of combo-boxes. To use it, just create an instance and then add all your combo-boxes using its addCombo method.

enter image description here

Demo Script:

import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *

class ExclusiveComboGroup(QObject):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._combos = []
        self._role = Qt.UserRole + 500

    def addCombo(self, combo):
        combo.activated.connect(
            lambda: self.handleActivated(combo))
        self._combos.append(combo)

    def handleActivated(self, target):
        index = target.currentIndex()
        groupid = id(target)
        for combo in self._combos:
            if combo is target:
                continue
            previous = combo.findData(groupid, self._role)
            if previous >= 0:
                combo.view().setRowHidden(previous, False)
                combo.setItemData(previous, None, self._role)
            if index > 0:
                combo.setItemData(index, groupid, self._role)
                combo.view().setRowHidden(index, True)

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.group = QGroupBox('Selected Tug')
        layout = QVBoxLayout(self)
        layout.addWidget(self.group)
        layout = QFormLayout(self.group)
        layout.setVerticalSpacing(15)
        layout.setHorizontalSpacing(50)
        jeju_tug = [
            'No use',
            '207HR (2,500HP)',
            '306DR (3,600HP)',
            'Jupiter (3,600HP)',
            ]
        # create a combo-group
        self.tugs = ExclusiveComboGroup(self)
        for index in range(3):
            combo = QComboBox(self)
            combo.addItems(jeju_tug)
            layout.addRow(f'Tug {index + 1}', combo)
            # add the combo-box
            self.tugs.addCombo(combo)

if __name__ == "__main__":

    app = QApplication(sys.argv)
    window = Window()
    window.setWindowTitle('Demo')
    window.setGeometry(800, 200, 100, 50)
    window.show()
    sys.exit(app.exec_())

PS: here is how to use it in your own example:

def initUI(self):
    tug1_cb = QComboBox(self)
    jeju_tug = ['No use','207HR (2,500HP)', '306DR (3,600HP)', 'Jupiter (3,600HP)']
    tug1_cb.addItems(jeju_tug)

    tug2_cb = QComboBox(self)
    tug2_cb.addItems(jeju_tug)

    tug3_cb = QComboBox(self)
    tug3_cb.addItems(jeju_tug)
    
    # copy the ExclusiveComboGroup class into
    # your code and then add this section
    tugs = ExclusiveComboGroup(self)
    tugs.addCombo(tug1_cb)
    tugs.addCombo(tug2_cb)
    tugs.addCombo(tug3_cb)
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thank you for your kind solution!! However sir, I have one more Question. How can I place the 'QGroupbox', 'Labels' and 'Qcombobox' by using '.move' to where i want? – Woody Kim Feb 08 '21 at 03:46
  • 1
    @WoodyKim I have shown how to do it at the end of my answer. Copy **only** the `ExclusiveComboGroup` class into your code, then create an instance of it and add your combo-boxes. You don't need anything else from the demo script. (PS: if you found my answer useful, please accept it - i.e. click on the tick mark above). – ekhumoro Feb 08 '21 at 05:20
  • OMG. It works!! Thank you for your genius solution. I have squeezed my brain for this for almost 1 month but you solved it at once!! I have ticked your answer above mark already!! Thank you sir!!!:)) – Woody Kim Feb 08 '21 at 06:23
  • Sir, I have try to understand the code your wrote above 'class ExclusiveComboGroup(Qobject) ' part, but in my short coding experience, I am not able to understand.....if you explain the principle of the code and the signal goes to where to where and it works, it will be more helpful for your reputation. Thank you sir – Woody Kim Feb 11 '21 at 08:44
  • 1
    @WoodyKim The activated signal is emitted whenever the user chooses an item in the combo box. It is connected to the `handleActivated` method, which updates the other combo-boxes. The item-data in each combo-box records the id of whichever other combo-box has that item as its current-item, and hides/shows the item as necessary. – ekhumoro Feb 11 '21 at 16:51