Right now I'm working on a program using wxPython, and I want to make a GUI in which under certain conditions, the widgets become inactive and the user can't interact with them. I'm pretty sure I have seen this in programs before, but I can't come up with a specific example. Is there a way to do this in wxPython? I have no idea what the technical name for this is, so even giving me that would be helpful.
When you say "the objects", what do you mean? If you mean a wx Frame, then you can call Frame.Freeze() to disable the frame, and Frame.Thaw() to unfreeze it. If you want to create a new dialog that must be interacted with and make all background windows unuseable, you can call Dialog.ShowModal(). Finally, many widgets have a Widget.Enable() function, to which you can pass True or False depending on if you want to enable it or not.
Related
I'm working on a custom cross platform UI library that needs a synchronous "ShowPopup" method that shows a popup, runs an event loop until it's finished and automatically cancels when clicking outside the popup or pressing escape. Keyboard, mouse and scroll wheel events need to be dispatched to the popup but other events (paint, draw, timers etc...) need to be dispatched to their regular targets while the loop runs.
Edit: for clarification, by popup, I mean this kind of menu style popup window, not an alert/dialog etc...
On Windows I've implemented this fairly simply by calling GetMessage/DispatchMessage and filtering and dispatching messages as appropriate. Works fine.
I've much less experience with Cocoa/OS X however and finding the whole event loop/dispatch paradigm a bit confusing. I've seen the following article which explains how to implement a mouse tracking loop which is very similar to what I need:
http://stpeterandpaul.ca/tiger/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/chapter_5_section_4.html
but... there's some things about this that concern me.
The linked article states: "the application’s main thread is unable to process any other requests during an event-tracking loop and timers might not fire". Might not? Why not, when not, how to make sure they do?
The docs for nextEventMatchingMask:untilDate:inMode:dequeue: states "events that do not match one of the specified event types are left in the queue.". That seems a little odd. Does this mean that if an event loop only asks for mouse events then any pressed keys will be processed once the loop finishes? That'd be weird.
Is it possible to peek at a message in the event queue without removing it. eg: the Windows version of my library uses this to close the popup when it's clicked outside, but leaves the click event in the queue so that clicking outside the popup on a another button doesn't require a second click.
I've read and re-read about run loop modes but still don't really get it. A good explanation of what these are for would be great.
Are there any other good examples of implementing an event loop for a popup. Even better would be pseudo-code for what the built in NSApplication run loop does.
Another way of putting all this... what's the Cocoa equivalent of Windows' PeekMessage(..., PM_REMOVE), PeekMessage(..., PM_NOREMOVE) and DispatchMessage().
Any help greatly appreciated.
What exactly is a "popup" as you're using the term? That term means different things in different GUI APIs. Is it just a modal dialog window?
Update for edits to question:
It seems you just want to implement a custom menu. Apple provides a sample project, CustomMenus, which illustrates that technique. It's a companion to one of the WWDC 2010 session videos, Session 145, "Key Event Handling in Cocoa Applications".
Depending on exactly what you need to achieve, you might want to use an NSAlert. Alternatively, you can use a custom window and just run it modally using the -runModalForWindow: method of NSApplication.
To meet your requirement of ending the modal session when the user clicks outside of the window, you could use a local event monitor. There's even an example of just such functionality in the (modern, current) Cocoa Event Handling Guide: Monitoring Events.
All of that said, here are (hopefully no longer relevant) answers to your specific questions:
The linked article states: "the application’s main thread is unable to process any other requests during an event-tracking loop and
timers might not fire". Might not? Why not, when not, how to make
sure they do?
Because timers are scheduled in a particular run loop mode or set of modes. See the answer to question 4, below. You would typically use the event-tracking mode when running an event-tracking loop, so timers which are not scheduled in that mode will not run.
You could use the default mode for your event-tracking loop, but it really isn't a good idea. It might cause unexpected re-entrancy.
Assuming your pop-up is similar to a modal window, you should probably use NSModalPanelRunLoopMode.
The docs for nextEventMatchingMask:untilDate:inMode:dequeue:
states "events that do not match one of the specified event types are
left in the queue.". That seems a little odd. Does this mean that if
an event loop only asks for mouse events then any pressed keys will be
processed once the loop finishes? That'd be weird.
Yes, that's what it means. It's up to you to prevent that weird outcome. If you were to read a version of the Cocoa Event Handling Guide from this decade, you'd find there's a section on how to deal with this. ;-P
Is it possible to peek at a message in the event queue without removing it. eg: the Windows version of my library uses this to close
the popup when it's clicked outside, but leaves the click event in the
queue so that clicking outside the popup on a another button doesn't
require a second click.
Yes. Did you notice the "dequeue:" parameter of nextEventMatchingMask:untilDate:inMode:dequeue:? If you pass NO for that, then the event is left in the queue.
I've read and re-read about run loop modes but still don't really get it. A good explanation of what these are for would be great.
It's hard to know what to tell you without knowing what you're confused about and how the Apple guide failed you.
Are you familiar with handling multiple asynchronous communication channels using a loop around select(), poll(), epoll(), or kevent()? It's kind of like that, but a bit more automated. Not only do you build a data structure which lists the input sources you want to monitor and what specific events on those input sources you're interested in, but each input source also has a callback associated with it. Running the run loop is like calling one of the above functions to wait for input but also, when input arrives, calling the callback associated with the source to handle that input. You can run a single turn of that loop, run it until a specific time, or even run it indefinitely.
With run loops, the input sources can be organized into sets. The sets are called "modes" and identified by name (i.e. a string). When you run a run loop, you specify which set of input sources it should monitor by specifying which mode it should run in. The other input sources are still known to the run loop, but just ignored temporarily.
The -nextEventMatchingMask:untilDate:inMode:dequeue: method is, more or less, running the thread's run loop internally. In addition to whatever input sources were already present in the run loop, it temporarily adds an input source to monitor events from the windowing system, including mouse and key events.
Are there any other good examples of implementing an event loop for a popup. Even better would be pseudo-code for what the built in
NSApplication run loop does.
There's old Apple sample code, which is actually their implementation of GLUT. It provides a subclass of NSApplication and overrides the -run method. When you strip away some stuff that's only relevant for application start-up or GLUT, it's pretty simple. It's just a loop around -nextEventMatchingMask:... and -sendEvent:.
I have a rather unusual question, namely, how is called this window from icon tray?
I would like to make it in my application, and I could not find his name. I would ask for some information, or the name, the rest I should have to deal with.
The Windows UX Guidelines don't say anything about it. From my perspective it's just a normal dialog, albeit one that has rather immediate actions (as opposed to first clicking on an OK button of sorts) and resides in a fairly small size in a specific location. It is meant to be opened, interacted with quickly and then dismissed, never being the center of your attention. If your idea fits those criteria as well, then go ahead. It's easy to recreate with standard means.
I'm playing Skyrim in windowed mode and I am trying to create a bot for this game for personal use. I would like to have the bot play the game in the background, while I do other things, the only problem is that the game window pauses when it loses focus. Is there a way to make the Skyrim process think that it still has the focus, so it continues to run while I do something else on another window? I'm not a windows programming expert but would this be possible if I could somehow intercept the message that says unfocused or minimized to the process, and thus let the process think its still focused?
It's possible. You need to find the mechanism through which the game checks whether it's in the foreground then trick it into thinking the switch has not occurred. This will require a certain amount of reverse engineering on your part. There are many different ways that this checking can actually be done by the game.
You can try to play with hooking one of the following messages/functions: WM_KILLFOCUS, WM_ACTIVATE, GetForegroundWindow. On the other hand, the game might be doing something funky with DirectX. I don't have much experience there.
To re-iterate, to do this properly you are really going to have to find out exactly how the game does the checking (and then subvert that).
I am not sure which class I need. I am looking to implement the following:
User clicks on NSButton ( Have this working)
Have a background task run once he does this. (have this working)
While the task is in progress, I want to display a small popup which indicates the task is in progress and asks the user to wait/give him some more informtion. ( This is where I need help)
I am not really sure what class would help me get this popup..NSPopup /NsAlert ?
Appreciate any pointers. Thanks.
In addition to Peter's answer: Spend some time perusing Interface Builder's Library palette so you know what standard controls are available and what they're called. Spend more time reading the AppKit API reference to get a feel for how they work in general.
The specific control to display progress is an NSProgressIndicator. As Peter said, you can put this in a view or a sheet but the best approach really depends on the factors Peter mentioned.
It should simply be a view in your window.
If the user cannot do anything in the window until the operation finishes (and you should do everything you can to prevent such obstruction), then it should be a sheet over the window.
If the user can do more than one of these operations at the same time and they don't prevent the user from doing other things with the window, then a view in the window will become unwieldy, and you should move the progress display to a dedicated progress window, as done by Transmit, Mail, Adium, Finder, Amadeus Pro, and many other applications.
We are designing the UI for a new line of business application. We have no real constraints and are free to design the UI as we see fit. The UI will be done in WPF and targeted for Windows 7, Vista, and XP Pro users.
Many dialog boxes contain OK and Cancel buttons in their lower right corner. Do you feel it is necessary to have this Cancel button or is the red X in the upper right corner sufficient? We are discussing this as we have been noticing more UIs that do not have cancel buttons, only the red X.
Not only you should add it but also make sure ESC is mapped to it.
Present the two designs to the customer - one with the "Cancel" button, the other without. See what their thoughts are.
Better still present them as partially working prototypes and watch them as they use the dialogs. If you ask them to perform a set of tasks and see if they have trouble when asked to cancel an operation.
Having said that, my preference is to include a "Cancel" button for the reasons others have mentioned:
Accessibility (especially as Esc should be mapped to it).
Convention (users will be expecting it).
Include the Cancel button. The red X is VERY hard to tab to. ;)
Include it. This is very common in other user interfaces. Give the user the choice of which to use; making it for them might make them annoyed with your interface.
Users are used to having standard GUI layouts - otherwise they get confused. They also have different ways of using the standard interface. Some people only use the X, some people only use Cancel. People usually ignore the one they're not using, but get confused if their one isn't present. So be safe and keep them both in - it should only be a one-liner function for Cancek anyway.
Include it!
From a user interface perspective, not including a cancel button might leave some users feeling like they have no choice, which is certainly not the case. Imagine the following simple decision scenario:
Warning: All of the files in the selected folder will be deleted. This action cannot be undone. Are you sure you would like to continue?
How silly would an interface be if the only option was Ok? Also, as noted above, on many platforms the Escape key is mapped to Cancel. It's also probably worthwhile setting a default button so that pressing the Enter/Space key doesn't inadvertently perform the action that cannot be undone.
+1 on including it. If you don't include it now and then need some different functionality on Cancel to Close later on, your users will already be used to automatically closing.
Just like we have 'ESC' button on keyboard, we need 'Cancel' in dialogs.
A matter of usability :-)
Include it. And please also make sure that you make sure that hitting the Escape key does the same thing as the Cancel button.
Also, just because you're designing from scratch, please don't throw out all convention. Take a look at MSFT's UX Guidelines for dialog boxes.
The red button is really for 'Close' rather than 'Cancel'. 'Cancel' canceling a running task. Use a 'Close' button instead. And yes include the 'Close' if there is a reason for people to click on it. The red button is quite difficult to click when you really want to close something quickly.
If you have that kind of freedom, consider eliminating dialog boxes from your application entirely, especially ones with the typical "OK | CANCEL" paradigm. Dialog boxes disrupt the flow of action and generally should only be used for things which absolutely require the program to interrupt the user.
You'll notice how disruptive they are in the web environment -- e.g., Stack Overflow only uses them when it needs to be able to OVERRIDE your action, e.g., when you navigate away from an unsubmitted answer.