Menu Actions with variable number of actions
-
I'm trying to create a menu item that has a variable number of options dependent on what is in a MySQL database. Right now I have the following (pseudo)code:
def __init__(self, db, parent, logger=None): self.menu = QMenuBar(parent) self.parent = parent bookmarks = self.menu.addMenu("Bookmarks") bookmarks = self.menu.addMenu("Bookmarks") for action in self.createBookmarks(): bookmarks.addAction(action) def createBookmarks(self): self.bookmarkData = self.db.getBookmarks() for i in range(self.bookmarkData.shape[0]): action = QAction(self.bookmarkData.Name[i], self.parent) action.setStatusTip("Go to {}".format(self.bookmarkData.Name[i])) action.triggered.connect(lambda: self.parent.go_to_URL(QUrl("{}".format(self.bookmarkData.Address[i])))) yield action
where
self.db.getBookmarks()
returns a pandas DataFrame object that isName Address Facebook www.facebook.com Instagram www.instagram.com DuckDuckGo www.duckduckgo.com : : :
and the idea is to create a menu that adjusts the entries dependent on what is in the database table. Right now the bookmarks menu is set up correctly, but all actions go to the very last entry that was created in the menu (in the example data I provided it would always go to
www.duckduckgo.com
no matter what you click on). Can you please help me fix how the bookmarks menu is created to connect to the correct addresses? -
@SGaist can you please help me fix my lambda invocation? I'm new to using lambdas. Thank you.
This stack overflow answer shows it nicely.
The short version is:
bookmarked_url = QUrl("{}".format(self.bookmarkData.Address[i])) action.triggered.connect(lambda url=bookmarked_url: self.parent.go_to_URL(url))
Beware that you are creating objects that can be garbage collected when doing so. I strongly encourage you to refactor your code following my suggestion above.
-
Hi and welcome to devnet,
Your code issue is that you are not capturing the variable in your lambda.
That said, you have a design issue. Child widgets should not know anything about their parent. This create tight coupling which is bad.
To have something cleaner, you should add a signal (for example bookmarkActivated) to your current widget and connect your parent to that signal. Then in your current widget, have a private slot that will emit the signal based on the action triggered.
-
Hi and welcome to devnet,
Your code issue is that you are not capturing the variable in your lambda.
That said, you have a design issue. Child widgets should not know anything about their parent. This create tight coupling which is bad.
To have something cleaner, you should add a signal (for example bookmarkActivated) to your current widget and connect your parent to that signal. Then in your current widget, have a private slot that will emit the signal based on the action triggered.
-
@SGaist can you please help me fix my lambda invocation? I'm new to using lambdas. Thank you.
This stack overflow answer shows it nicely.
The short version is:
bookmarked_url = QUrl("{}".format(self.bookmarkData.Address[i])) action.triggered.connect(lambda url=bookmarked_url: self.parent.go_to_URL(url))
Beware that you are creating objects that can be garbage collected when doing so. I strongly encourage you to refactor your code following my suggestion above.
-