How to implement findChildren() universally ?
-
Hey!
MainWindow imports Dialog which imports CustomWidget
In CustomWidget the MainWindow is the grandparent:
actions = self.parentWidget().parentWidget().findChildren(QAction)MainWindow imports CustomWidget
In CustomWidget the MainWindow is the parent:
actions = self.parentWidget().findChildren(QAction)How to implement findChildren() so that it works in both cases?
Thanks
-
Hey!
MainWindow imports Dialog which imports CustomWidget
In CustomWidget the MainWindow is the grandparent:
actions = self.parentWidget().parentWidget().findChildren(QAction)MainWindow imports CustomWidget
In CustomWidget the MainWindow is the parent:
actions = self.parentWidget().findChildren(QAction)How to implement findChildren() so that it works in both cases?
Thanks
@NonNT
There i something wrong here. Either something is a parent or a grandparent or whatever, but what you import makes no difference either way. Parentage is to do with how widgets are added where, not by what is imported.Having said that: there is (almost certainly) something wrong with your logic if from within a child/custom widget you are reaching up to its parent/grandparent and doing something there, like looking for children. Essentially widgets should not need to know anything about their parent; they may look at their own children, but should no be relying on their parent being anything in particular. Urge you to reconsider your approach, before your code turns into a spaghetti-mess!
-
# This Python file uses the following encoding: utf-8 import sys from PySide2.QtWidgets import QApplication from main_window import MainWindow if __name__ == "__main__": app = QApplication(sys.argv) app.setOrganizationName('pyTest') app.setApplicationName('Keyboard Shortcuts') app.setApplicationDisplayName('Keyboard Shortcuts') window = MainWindow() window.show() sys.exit(app.exec_())main_window.py
# This Python file uses the following encoding: utf-8 import sys from PySide2.QtCore import Qt from PySide2.QtGui import QIcon, QKeySequence from PySide2.QtWidgets import QAction, QApplication, QMainWindow, QMenu from keyboard_shortcuts_dialog import KeyboardShortcutsDialog from keyboard_shortcuts_table import KeyboardShortcutsTable class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.resize(QApplication.desktop().availableGeometry(self).width() / 2, QApplication.desktop().availableGeometry(self).height() / 2); self.move((QApplication.desktop().availableGeometry(self).width() - self.width()) / 2, (QApplication.desktop().availableGeometry(self).height() - self.height()) / 2); actionQuit = QAction('Quit', self) actionQuit.setIcon(QIcon.fromTheme('application-exit')) actionQuit.setShortcut(QKeySequence.Quit) actionQuit.setToolTip('Quit the application') actionQuit.triggered.connect(self.close) actionKeyboardShortcuts = QAction('Keyboard Shortcuts', self) actionKeyboardShortcuts.setIcon(QIcon.fromTheme('help-keybord-shortcuts')) actionKeyboardShortcuts.triggered.connect(self.onActionKeyboardShortcutsTriggered) menu = self.menuBar().addMenu('Application') menu.addAction(actionKeyboardShortcuts) menu.addSeparator() menu.addAction(actionQuit) # Main widget self.setCentralWidget(KeyboardShortcutsTable(self)) def onActionKeyboardShortcutsTriggered(self): dialog = KeyboardShortcutsDialog(self) dialog.setWindowTitle('Keyboard Shortcuts') dialog.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) dialog.show()keyboard_shortcuts_dialog.py
# This Python file uses the following encoding: utf-8 from PySide2.QtWidgets import QApplication, QDialog, QDialogButtonBox, QVBoxLayout from keyboard_shortcuts_table import KeyboardShortcutsTable class KeyboardShortcutsDialog(QDialog): def __init__(self, parent=None): super(KeyboardShortcutsDialog, self).__init__(parent) self.resize(QApplication.desktop().availableGeometry(self).width() / 3, QApplication.desktop().availableGeometry(self).height() / 3); self.move((QApplication.desktop().availableGeometry(self).width() - self.width()) / 2, (QApplication.desktop().availableGeometry(self).height() - self.height()) / 2); buttonBox = QDialogButtonBox(QDialogButtonBox.Close) buttonBox.rejected.connect(self.close) # Main layout layout = QVBoxLayout() layout.addWidget(KeyboardShortcutsTable(self), 1) layout.addWidget(buttonBox) self.setLayout(layout)keyboard_shortcuts_table.py
# This Python file uses the following encoding: utf-8 from PySide2.QtCore import Qt from PySide2.QtGui import QKeySequence from PySide2.QtWidgets import QAction, QMainWindow, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget class KeyboardShortcutsTable(QWidget): def __init__(self, parent=None): super(KeyboardShortcutsTable, self).__init__(parent) labels = ['Name', 'Shortcut', 'Description'] shortcutItems = [] # Only works if MainWindow is parent actionItems = self.parentWidget().findChildren(QAction) # Only works if MainWindow is grandparent #actionItems = self.parentWidget().parentWidget().findChildren(QAction) for actionItem in actionItems: if not actionItem.shortcut().isEmpty(): shortcutItems.append(actionItem) tableBox = QTableWidget(len(shortcutItems), len(labels), self) tableBox.setHorizontalHeaderLabels(labels); tableBox.horizontalHeader().setDefaultAlignment(Qt.AlignLeft) tableBox.horizontalHeader().setStretchLastSection(True) tableBox.verticalHeader().setVisible(False) row = 0 for shortcutItem in shortcutItems: tableBox.setItem(row, 0, QTableWidgetItem(shortcutItem.text())) tableBox.setItem(row, 1, QTableWidgetItem(shortcutItem.shortcut().toString(QKeySequence.NativeText))) tableBox.setItem(row, 2, QTableWidgetItem(shortcutItem.toolTip())) row += 1 # Main layout layout = QVBoxLayout() layout.addWidget(tableBox, 1) self.setLayout(layout)<--->
# Only works if MainWindow is parent actionItems = self.parentWidget().findChildren(QAction) # Only works if MainWindow is grandparent #actionItems = self.parentWidget().parentWidget().findChildren(QAction)So how can this be done universally?
-
Hi,
Are you trying to implement some sort of action editor ?
-
I have changed it like this:
class KeyboardShortcutsTable(QWidget): def __init__(self, mainWindowWidget, parent=None): ... actionItems = mainWindowWidget.findChildren(QAction) ...class KeyboardShortcutsDialog(QDialog): ... layout.addWidget(KeyboardShortcutsTable(self.parentWidget()), 1) ...It works, but I am not sure if it is the best solution.
-
I have changed it like this:
class KeyboardShortcutsTable(QWidget): def __init__(self, mainWindowWidget, parent=None): ... actionItems = mainWindowWidget.findChildren(QAction) ...class KeyboardShortcutsDialog(QDialog): ... layout.addWidget(KeyboardShortcutsTable(self.parentWidget()), 1) ...It works, but I am not sure if it is the best solution.
@NonNT
This means thatKeyboardShortcutsDialogis tied to showing theQActions of whatever its parent widget is. Which is not bad, but if you're asking me I would remove that dependency.You are already passing the desired widget as a parameter to your
KeyboardShortcutsTable, which is good. Why not take it a step further, and pass it as a parameter toKeyboardShortcutsDialog, which in turn can pass it on toKeyboardShortcutsTable? Do you requireKeyboardShortcutsDialogto only be able to show the shortcuts of its own parent widget, rather than of any widget passed to it?class MainWindow(QMainWindow): def onActionKeyboardShortcutsTriggered(self): dialog = KeyboardShortcutsDialog(self, self) class KeyboardShortcutsDialog(QDialog): def __init__(self, actionsWidget, parent=None): ... self.actionsWidget = actionsWidget ... layout.addWidget(KeyboardShortcutsTable(self.actionsWidget), 1) ... class KeyboardShortcutsTable(QWidget): def __init__(self, actionsWidget, parent=None): ... actionItems = actionsWidget.findChildren(QAction) ...No parenting-dependencies here! I might pass
actionsWidget.findChildren(QAction)as the parameter, receiving a list ofQActions instead of aQWidget, depending on whether I really need to access the widget rather than just its actions. -
KeyboardShortcutsTableis tied to the parent widget.
I thought that you could call thefindChildren(QAction)or something similar inKeyboardShortcutsTableto get the list of actions without passing the MainWindow widget.
But it works now. Thanks@NonNT
Well you can if you specify the correct parentage. If you are insideKeyboardShortcutsTableyou presumably have to go up to itsKeyboardShortcutsDialog, and then from there up to theMainWindow.But I think its preferable to pass the
MainWindowwidget explicitly, then your table is not tied to where it happens to be situated/called from.
