I am building a Qt application on Linux. I have a menu bar in the main window with two menus in it, each with several actions, all of which have keyboard shortcuts associated with them. The keyboard shortcuts work when the menus are not open, but when one of the menus is open, none of them work.
The shortcuts were added to the actions with setShortcut prior to the actions being added to their respective menus with [menuobject]->addAction. All the actions have the main window as their parent. After reading QAction shortcut doesnt always work I added calls to addAction, adding the action to the main window. This did not correct the problem.
Example of the code for one of the menu items:
//In the main window constructor
gameQuit = new QAction(QString(tr("&Quit\tCtrl+Q")), this);
gameQuit->setShortcut(QKeySequence(Qt::Key_Q | Qt::CTRL));
addAction(gameQuit);
connect(gameQuit, SIGNAL(triggered()), this, SLOT(close()));
gameMenu = menuBar()->addMenu(QString(tr("&Game")));
gameMenu->addAction(gameQuit);
In QtCreator, which I assume was written with Qt, the keyboard shortcuts for the menu items do work when the menus are open, so I think there must be a way.
Thanks for any help.
Taking some advice from the comments of the cited post (which had been rebuked, which is why I didn't try it initially), I modified the shortcut context using [actionobject]->setShortcutContext(). Apparently the default does not work in my scenario.
I first tried setting to Qt::WindowShortcut, which didn't work. Qt::ApplicationShortcut did work, however, this may have shortcomings as noted in the comments of the cited post. They don't happen to matter for this particular application of mine though, so I am going to post and accept this as the answer.
Example of the correcting code:
//In the constructor of the main window, after creation of the action and
//setting of the shortcut
gameQuit->setShortcutContext(Qt::ApplicationShortcut);
Related
Beginner in the whole Python/Anki thing. Learning more about coding for fun and I have set up a debugging environment with pycharm and an Anki profile with the bazelfixes and it seems to start anki up fine. I want to append an extra dropdown menu on the main menu toolbar in Anki so that I can connect the actions to my functions.
I went through the hooks and the toolbar hook worked but it is not exactly what I was going for because it adds to the toolbar, not the menu. I want to add a new dropdown into the actual main menu next to tools, help, etc. connect them to functions I have made. Kind of like this
I have looked at others and sometimes they work partially but it's like a fragmented puzzle some use qmainwindow and it makes a popup separate from anki when I run it, or other approaches where they use the aqt.mw.form() functions in various ways but when I do it it will be like "nonetype doesn't take .form function." or form is not an expected argument. I want to figure out the first basic step.
I have also looked at the aqt MW thing but I am kind of confused about how it works so I am not sure if that is a better approach to read up on. The whole class>def variable> mw.append type of structure I have been seeing in other's code is a little confusing for me. Or am I going about it the completely wrong way and should use html/CSS? Any help or advice is greatly appreciated!
Also here is the bazelfixes code I have been using on pycharm.
try:
import bazelfixes
bazelfixes.fix_pywin32_in_bazel()
bazelfixes.fix_extraneous_path_in_bazel()
bazelfixes.fix_run_on_macos()
except ImportError:
pass
if not os.environ.get(“ANKI_IMPORT_ONLY”):
aqt.run()
TL;DR How do I, within this code on pycharm append an extra dropdown item on the main menu bar. Is there a hook I am missing (not the init toolbar one)? Or a different approach I should try?
How can I can a function and create a function for the icon context menu? I want to make the iconic Open New Window function pop-up when you right click on the icon menu in the taskbar/dock. See this question for more info on this kind of question.
Places I have looked but found nothing:
https://www.tcl.tk/man/tcl8.5/TkCmd/tk_mac.html#M15
https://pyinstaller.org/en/stable/feature-notes.html#open-event-handling-in-a-tkinter-based-gui-application
While there are a tiny subset of apple events that you can benefit from the DockMenu is not accessible directly via tkinter. Turns out mac is not really open for modifications and even smaller tasks can be hard. You could consider to use a system tray icon instead.
Is there a quick way to clear the menu bar i.e. Remove all menus in PyQt.
The reason I ask is that I am developing a modular application. Each module provides it's own menus and gives a weighting to where that menu should appear. Each module can also add a menuAction to another modules menu, however when that happens it changes the order of the menus. What i want to do is when the menus have finished being created is to remove them all and then re add them.
I know this will work because I can re add them now and they appear in the correct order but all the previous menus are still there.
did you try QMenu.clear (self)
mymenu = QtGui.QMenu("Menu")
mymenu.clear()
I'm writing a document based application in wxPython, by which I mean that the user can have open multiple documents at once in multiple windows or tabs. There are multiple kinds of documents, and the documents can all be in different "states", meaning that there should be different menu options available in the main menu.
I know how to disable and enable menu items using the wx.EVT_UPDATE_UI event, but I can't figure out how to pull off a main menu that changes structure and content drastically based on which document that currently has focus. One of my main issues is that the main menu is created in the top level window, and it has to invoke methods in grand children and great grand children that haven't even been created yet.
Contrived example; when a document of type "JPEG" is open, the main menu should look like:
File Edit Compression Help
And when the user switches focus (CTRL+Tab) to a document of type "PDF", the main menu should change to:
File Edit PDF Publish Help
And the "Edit" menu should contain some different options from when the "JPEG" document was in focus.
Current I'm just creating the menu in a function called create_main_menu in the top level window, and the document panels have no control over it. What would be necessary to pull off the kind of main menu scheme I describe above, specifically in wxPython?
I've figured out a pretty clean way to do this. First of all I create my "base" main menu bar, which contains the File and Help menu items. Then I defined a class EditorPanel than is a subclass of wx.Panel and defined the methods bind_main_menu_bar and release_main_menu_bar. The first of those methods receives the main menu bar when the panel is focused, and adds some items to it. Here is one of my implementations:
def bind_main_menu_bar(self, main_menu_bar):
main_frame = wx.GetApp().GetTopWindow()
self.main_menu_bar = main_menu_bar
# Create the edit menu.
self.edit_menu = edit_menu = shared.create_menu([
(const.ID_UNDO, self.LABEL_UNDO_EMPTY),
(const.ID_REDO, self.LABEL_REDO_EMPTY)
])
# Create the tools menu.
self.tools_menu = tools_menu = shared.create_menu([
(const.ID_SELECT_ADDRESS_COLUMNS, 'Select address columns...'),
(),
(const.ID_VALIDATE_ADDRESSES, 'Validate selected addresses'),
(const.ID_VALIDATE_ALL_ADDRESSES, 'Validate all addresses')
])
# Bind some menu event handlers to the main frame.
main_frame.Bind(wx.EVT_MENU, self.on_menu)
main_frame.Bind(wx.EVT_UPDATE_UI, self.on_menu_update)
# Insert the new menus into the main menu bar.
main_menu_bar.Insert(1, edit_menu, 'Edit')
main_menu_bar.Insert(2, tools_menu, 'Tools')
Now, when that editor panel is opened, the main menu receives an Edit menu and a Tools menu that is bound to event handlers in the EditorPanel, which is incredibly handy. When the editor loses focus, the release_main_menu_bar method is called, which should restore the main menu bar to it's original state. This is counterpart of the code above:
def release_main_menu_bar(self):
main_frame = wx.GetApp().GetTopWindow()
# Unbind the menu event handlers from the main frame.
main_frame.Unbind(wx.EVT_MENU, handler=self.on_menu)
main_frame.Unbind(wx.EVT_UPDATE_UI, handler=self.on_menu_update)
# Remove the edit and tools menu from the main menu bar.
self.main_menu_bar.Remove(1)
self.main_menu_bar.Remove(1)
# Reset the fields used for the menu.
self.edit_menu = None
self.tools_menu = None
self.main_menu_bar = None
So every editor that wants to edit the main menu just has to subclass those two methods and they have full control. The main frame will monitor when the user switches between editors and call the methods accordingly. The biggest problem was to figure out when the editor panel receives and loses focus, which is the topic of another question of mine: How do I monitor when wx.Panel receives and loses focus?
Probably the only way to do it with the standard wx.Menu is to destroy and recreate the entire menubar. You might be able to Hide it though. Either way, I think it would be easiest to just put together a set of methods that creates each menubar on demand. Then you can destroy one and create the other.
You might also take a look at FlatMenu since it is pure Python and easier to hack.
I have a Qt program with many buttons, user-interactable widgets, etc.
At one stage in the program, I would like all the widgets to temporarily 'stop working'; stop behaving to mouse clicks and instead pass the event on to one function.
(This is so the User can select a widget to perform meta operations. Part explanation here: Get variable name of Qt Widget (for use in Stylesheet)? )
The User would pick a widget (to do stuff with) by clicking it, and of course clicking a button must not cause the button's bound function to run.
What is the correct (most abstracted, sensible) method of doing this?
(which doesn't involve too much new code. ie; not subclassing every widget)
Is there anything in Qt designed for this?
So far, I am able to retrieve a list of all the widgets in the program (by calling
QObject.findChildren(QtGui.QWidget)
so the solution can incorporate this.
My current horrible ideas are;
Some how dealing with all the applications events all the time in one
function and not letting through the events when I need the
application to be dormant.
When I need dormancy, make a new transparent widget which recieves
mouse clicks and stretch it over the entire window. Take coordinates
of click and figure out the widget underneath.
Somehow create a new 'shell' instance of the window.
THANKS!
(Sorry for the terrible write-up; in a slight rush)
python 2.7.2
PyQt4
Windows 7
You can intercept events send to specific widgets with QObject::installEventFilter.
graphite answered this one first so give credit where credit is due.
For an actual example in PySide, here's an example you might draw some useful code from:
my_app.py
from KeyPressEater import KeyPressEater
if __name__ == "__main__":
app = QApplication(sys.argv)
eater = KeyPressEater()
app.installEventFilter(eater)
KeyPressEater.py
class KeyPressEater(QObject):
# subclassing for eventFilter
def eventFilter(self, obj, event):
if self.ignore_input:
# swallow events
pass
else:
# bubble events
return QObject.eventFilter(self,obj,event)