I have a canvas that is covered by many...many images. Most overlap each other sometimes 10 deep. A simple example is
a1 = self.Canvas.create_rectangle(0,0,100,100,fill="red")
self.Canvas.tag_bind(a1,"<Button-1>",self.eventa1)
b1 = self.Canvas.create_rectangle(0,0,100,100,fill="green")
self.Canvas.tag_bind(b1,"<Button-1>",self.eventb1)
c1 = self.Canvas.create_rectangle(0,0,100,100,fill="blue")
self.Canvas.tag_bind(c1,"<Button-1>",self.eventc1)
The top layer shows blue. I click on it and eventc1 is called as expected.
I was wondering if there is any way when I click on position X, Y to get each event covering that point (red, green and blue layer in this case) to fire the corresponding event for that layer in order top to bottom.
Or can the blue event processing have a way to cause the next lower layer' event to automatically fire. There is no way the blue event knows what it is sitting on top of. 20 years ago, I used GTK+ in C and it allowed an event to return an indication to fire a lower level event or not.
Your code does not look at all like C I must say. Looks more like some slippery slithery language...
In GTK you can customise a widget to your hearts content. GtkDrawingArea is typically used when you want to tinker around UI side too. You can override the event handlers for mouse interaction e.g.: widget_klass->button_press_event, widget_klass->motion_notify_event widget_klass->button_release_event and widget_klass->expose_event. You can make your own signal handlers with g_signal_new and fire off which ever one (or multiple ones thereof) you want according to where the click is in each of your custom event handlers. Make sure to add gtk_widget_add_events(widget, GDK_BUTTON_PRESS_MASK|etc...) to enable these events in your classes init function.
Enforcing a strict signal handling order might be a bit more complicated. The signals have the option for G_SIGNAL_RUN_FIRST etc, and you could get 3 running a strict order this way though there's always the chance that the event loop may receive signals at two different stages. Best would be to fire off the one signal with data provided that would list the functions to call and order in which they need to be invoked.
So yes you can do that in C, though it might be tricky. I'm pretty sure all the bindings don't loose functionality so you should be able to do it in almost any language, but as for all non-c coding, when you want to delve deep, the deobfuscation places you on a slippery slope. If you know how to do it in C, skip the snakes and ladders game and write it in C. If you've got boss/team constraints, port it when done, to make people happy - I believe there is enough consistency across the GTK API bindings that it shouldn't be too much of an issue. But being forced to think in a ladedah mindset of simpleness and being expected to achieve fine detailed complex solutions is just untenable.
Related
enter image description here
enter image description here
I want to draw a figure on another application as above. How can I do that? I tried using a window handle in c#, so I didn't get the result I wanted.
You could draw a transparent window on top of your target application, effectively creating an overlay. This would most likely involve quite a bit direct usage of the Win32 API. See for example enumerating windows of another application.
But it will likely be an unreliable solution since there is a whole bunch of things you need to take into account:
Ensure that the target application still receives all input events.
Ensure that your transparent window stays on top of the target application
Monitor the target application for any window size change, or minimizing/maximizing
Many more things that you will likely discover later
Note that this will likely not work for full screen applications, and while this should allow for an overlay, any data on what or where to draw things need to come from somewhere else.
I have a wxPython application with a multi-stage GUI. First a simple form pops for selecting from one of many (> 100) options (it's a part number list with a search box). Once the user has made their selection it builds the appropriate form and shows it, hiding the initial selection dialog. Due to the nature of this project, each secondary form has several matplotlib figures in a Notebook, around 7 or 8 figures each with 2-5 axes each. Because of this, the form takes several seconds between initialization and when it can be shown on the screen.
Does wxPython have a way to build a frame in the background? I don't mind forcing the user to wait a short while before it can be shown, but as it is right now building the form hogs the event loop and everything becomes unresponsive. If I use a thread to build the form, it completes successfully but when I call .Show() nothing happens and there's no error message.
As you can imagine, such a GUI has fairly complex code so it would be difficult to show a SSCCE (and it's not open source). If needed I can try to hack together something that would approximate my problem.
I have used BusyInfo before to tell the user that something is happening. You would put that in your frame's init() BEFORE you actually start creating the matplotlib figures. You can read about it here:
http://wiki.wxpython.org/BusyInfo
Another idea would be to create a second frame with a progressbar in it and a message. The progressbar would be set to just bounce back and forth and when you got done creating the matplot stuff, you would close the second frame.
Mike's idea of using wxBusyInfo is useful when something takes a long time, but it's possible you could make it take less time instead (or at least as well).
First, when inserting many (although I wouldn't say that 100 is that many, 1000 however definitely is) items into a wxChoice, freeze it before adding them -- and thaw it afterwards. This should cut down the time needed for the insertion drastically.
Second, creating all controls of a multi-page wxNotebook (or another wxBookCtrl) can be long, even in C++. So the idea is to not do it immediately but only create the controls of the page you are going to initially show to the user. And then create the other pages controls only when the user is about to select them, i.e. in your wxEVT_BOOKCTRL_PAGE_CHANGING event handler.
If you put this in place, you might not need wxBusyInfo any longer...
Some GUI's libraries have spin button widget with optional feature - acceleration.
When holding down one of the buttons (up or down) - as a result an acceleration of change in the value according to how long it is depressed.
Is this feature in wx.SpinButton and what's the best way to implement it?
No, that's not a built in feature of the SpinButton. Note that the SpinButton isn't implemented cross-platform, so you might want to look at wx.SpinCtrl or FloatSpin. Anyway, to implement what you want, you could probably catch the wx.EVT_SPIN and start a wx.Timer. When the timer hits some pre-determined value, you could start updating the control yourself. I'm not sure if this would work as you would be trying to update a widget that is already being updated, but it might...
Of course, you'd also have to bind to the mouse up event to stop the timer and stop the updates. I suspect you my have to roll your own widget though...
I would ask on the wxPython mailing list. Someone there might have more ideas.
I´d like to create a program which will react on actions by user in real time. For example there will be three Labels. And when user clicks on one, I want to recolor the border to a different color and the user should be able to "type" a (single) number in this Label. I know about the Entry widget, but Labels are suitable for the whole application.
Thank you for any answers
Your question is too vague to answer precisely, but to specifically address each individual point:
Yes, it's possible to "react .. in real time" -- whenever an event is detected it will be acted upon as soon as possible.
Yes, it's possible to color the border of a widget when an event is detected
Yes, it's possible to type into a label. Though, obviously, the behavior is unusual and may not be what you expect.
I suspect none of those help you solve your real problem, but I have no idea what you're actually trying to accomplish.
In the same game as last time, I've ran into a new problem. When I move the mouse, FPS increases from around 60 to over 500. I know what you're thinking; it's not because of on_draw() getting fired each event (I think), since I already did override of pyglet.app.EventLoop.idle:
class EventLoop:
def idle(self):
pyglet.clock.tick(poll=True)
return pyglet.clock.get_sleep_time(sleep_idle=True)
pyglet.app.EventLoop = EventLoop()
Also I call flip() on the window in my drawing function. All the useless mouse motion events take up a lot of CPU, which is annoying. What can I do about it?
Edit
I added window.invalid = False to my drawing function and window.invalid = True to my update function, this seems to reduce CPU usage with other mouse actions.
Edit 2
The drawing function is a typical on_draw() function.
Edit 3
After some more investigating, it seems that all those events don't take that much CPU as I thought they would. Still it would be good to know if this is the way Pyglet is supposed to act, or if it's something that should be avoided.
All you should be doing on mouse events is updating your apps' model of the input control state and using that in the next regular scheduled update and redisplay of the world model (which is presumably much more complex with physics and rendering and stuff).
ie just because mouse events come in at ~300fps doesn't mean you actually have to do all the stuff you want to do at 300fps.
It's been a while since I did any Pyglet, but the pattern I seemed to use was to subclass Pyglet's window.Window as MyGameWindow, then that registered event handlers like
#self.event
def on_mouse_motion(x,y,dx,dy):
self.mouse_position=(x,y)
self.mouse_buttons=0
self.invalid = False
(also on_mouse_drag, on_mouse_press, on_mouse_release). Hmmm... actually, I think that assignment to self.invalid might have been crucial for overriding Pyglet's default behaviour and defering any further updating/drawing until the next "clock tick".