1

I have a GUI where a QListWidget is the central widget. The QListWidgetItems are composed of a custom widget that include a Graphics area and a QTable.

When I click on the graphics area, or on the table, the parent QListWidgetItem is not selected

See Picture of the GUI I'm working on

Gui

The red border around the top QListWidgetItem indicates that is the one that is currently selected.

From the Input on the table in the second QListWidgetItem, you can see I'm inputting text into the table widget there.

How can I make it so that if I click anywhere on that QListWidgetItem, including its child widgets, that the corresponding item is selected?

For reference, here is some of the relevant code:

class MainWindow(QMainWindow):
    move_splitter = Signal(int, int)

    def __init__(self):
        super().__init__()

        # stuff

        self.panels = QListWidget()
        self.panels.setAcceptDrops(True)
        self.panels.setDragEnabled(True)
        self.panels.setDragDropMode(QAbstractItemView.InternalMove)
        self.panels.setStyleSheet("QListWidget::item:selected \
        { border: 1px solid red }")
        self.panels.setSelectionMode(QAbstractItemView.SingleSelection)
        self.setCentralWidget(self.panels)

        # more stuff


    def add_panel(self):
        insert_item = QListWidgetItem()
        # Panel inherits from QWidget
        new_panel = Panel(parent=insert_item,
                          splitter_pos=self.initialSplitterPosition)
        self.move_splitter.connect(new_panel.setSplitterPosition)
        new_panel.slider_position.connect(self.slotSplitterPosition)
        insert_item.setSizeHint(new_panel.sizeHint())
        insert_item.setFlags(insert_item.flags() | Qt.ItemIsAutoTristate)
        insert_item.setCheckState(Qt.PartiallyChecked)
        self.panels.insertItem(self.panels.currentRow() + 1, insert_item)
        self.panels.setItemWidget(insert_item, new_panel)

EDIT:

With the suggestion of implementing an event filter, I created the following subclass of my table

class ControlTable(QTableWidget):
    focusReceived = Signal()

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

    def focusInEvent(self, event):
        if event.type() == QFocusEvent.gotFocus:
            self.focusReceived.emit()
        QTableWidget.focusInEvent(self, event)

In my panel function, I created a signal and a slot to capture that signal and emit a signal to the MainWindow with which QListWidgetItem should be selected

class Panel(QWidget):
    slider_position = Signal(int, int)
    select_me = Signal(QObject)

    def __init__(self, parent=None, splitter_pos=[]):
        # stuff
        self.table = ControlTable()
        self.table.focusReceived.connect(self.childWidgetFocus)
        # more stuff

    @Slot()
    def childWidgetFocus(self):
        parent = self.parent_item
        self.select_me.emit(parent)

In my mainwindow class I also added

def add_panel(self):
    insert_item = QListWidgetItem()
    new_panel = Panel(parent=insert_item,
                      splitter_pos=self.initialSplitterPosition)
    new_panel.parent_item = insert_item
    new_panel.select_me.connect(self.changeSelection)
    # more stuff

@Slot(QObject)
def changeSelection(self, item):
    item.setSelected(True)

While the code runs, the change of selection is not happening, am I implementing the wrong event filter?

EDIT2:

Got it working, was using the wrong event filter type, I needed to use QEvent.FocusIn, but now that I look at my code, and looking at the function I'm overwriting, that if statement is unnecessary it would seem.

I also had to change the signal pass type from QObject to QListWidgetItem.

Ogi Moore
  • 131
  • 9
  • did you add this line intentionally? ``insert_item.setCheckState(Qt.PartiallyChecked)`` . it might be the reason of your problem – Luchko Apr 23 '17 at 17:17
  • I put in that line as part of an earlier troubleshooting effort, but as far as I can tell, for my purposes, it makes no difference. I did just verify that by commenting the line out and rerunning. – Ogi Moore Apr 24 '17 at 02:58

1 Answers1

0

One possible but long way could be to set an event filter on each child of the item's widget (in your case its Panel) and select the the QListWidgetItem bound to the parent (Panel) from that event filter when focus is on the child element.

You can store the item reference in item attribute of Panel widget (you should create it) to make the item selection easier. So add before setItemWidget

new_panel.item = insert_item

In your event filter you can emit pyqtSignal passing self.parent().item as a parameter and further process it to select the corresponding item

some references which should help you to start:

How to change a parent widget's background when a child widget has focus?

Community
  • 1
  • 1
Luchko
  • 1,123
  • 7
  • 15