How to make tkinter Canvas update only on-demand? - python-3.x

I'm writing a graphics program in Python and I would like to know how to make a Canvas update only on-demand; that is, stop a canvas from updating every run of the event loop and instead update only when I tell it to.
I want to do this because in my program I have a separate thread that reads graphics data from standard input to prevent blocking the event loop (given that there's no reliable, portable way to poll standard input in Python, and polling sucks anyway), but I want the screen to be updated only at intervals of a certain amount of time, not whenever the separate thread starts reading input.

You can't pause the update of the canvas without pausing the entire GUI.
A simple solution would be for you to not draw to the canvas until you're ready for the update. Instead of calling canvas commands, push those commands onto a queue. When you're ready to refresh the display, iterate over the commands and run them.
You could also do your own double-buffering, where you have two canvases. The one you are actively drawing would be behind the visible one. When you are ready to display the results, swap the stacking order of the canvases.

Related

Vulkan image layout transition using render pass

I have a Vulkan renderer where a new render pass is started at the beginning of each frame. Then the command buffer is passed to several modules each of which submits some draw calls and other commands. Before the draw calls are submitted, it checks whether any additional textures have to be loaded which it does, at the end of the loading process an image layout transition to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL is performed.
The problem is that the layout transition uses a vkCmdPipelineBarrier command which only allows same format for input and output ( VUID-vkCmdPipelineBarrier-oldLayout-01181 ) which makes the transition useless for me.
My only solution at the moment is to move the layout transitions to a different command buffer and submit it to the command queue separately, then retrieve the result before continuing building my command buffer, but that means I have to wait for all previous commands in the queue to finish, right?
Can you imagine a cleaner solution for performing layout transitions between different layouts during an active render pass?
Regards
My only solution at the moment is to move the layout transitions to a different command buffer and submit it to the command queue separately, then retrieve the result before continuing building my command buffer, but that means I have to wait for all previous commands in the queue to finish, right?
You're not thinking fourth dimensionally.
The order you build the command buffers in is irrelevant. What matters is the order you submit them in.
The code which is building your rendering command buffer can also be building a transfer command buffer. You write your rendering command assuming the images are in the correct layout, and you write transfer commands which put those images into the right layout after the transfer is complete. The order you write these commands is irrelevant; the only order that matters is their submission order. Put one CB before the other in that order, and (barriers willing) they will execute appropriately in that order.
The CPU never needs to wait on anything. No "results" need to be retrieved; that's the GPU's job.
Being able to do this is why you have to tell Vulkan what the layout of each image is anytime you try to use it.

How to keep PyQt GUI responsive when blocking tasks are GUI related?

I'm writing an app that embeds a bunch of matplotlib figures into a PyQt GUI. The updating of these figures can take up to a few seconds, so I would like to introduce a waiting indicator to display while the plots are being drawn. I've moved all the data processing code into its own thread, but it seems the actual plotting calls are often making up the majority of processing time.
I have written a waiting indicator that uses a QTimer instance to trigger paintEvent on the widget. This works just fine when all the intensive processing can be pushed into another thread. The problem is that these calls to construct the matplotlib plots cannot be moved outside of the main thread due to the way Qt is designed, and so block the updating of the waiting indicator, rendering it kind of useless.
I've introduced some calls to QCoreApplication.processEvents() after the updating of each figure, which improves the performance a little. I've also toyed with the idea of monkeypatching a bunch of methods of matplotlib.axes.Axes to include calls to QCoreApplication.processEvents(), but I can see that getting messy. Is this the best I can do? Is there any way to interrupt the main thread at regular intervals and force it to process new events?
It should also help a big deal to do the actual drawing on a QPixmap in a thread. Drawing that pixmap with QPainters drawPixmap() method is very fast. And you need to recreate the pixmap only when really needed (e.g. after Zooming or so). In the meantime you just have to reuse that already drawn pixmap. The actual paintEvents using drawPixmap() will cost close to nothing and your GUI will be completely responsive.
Clobbering the code with processEvent() is not only ugly but can cause very nasty and very hard to debug malfunctions. E.g. it might cause premature deletion of objects which are still in use but were scheduled for deletion using deleteLater().
This Answer might be also of use: Python - matplotlib - PyQT: plot to QPixmap
I havn't used matplotlib, yet. But in case it uses directly QWidgets and can not be used without it won't be so easy as you mentioned above. But you could do the drawing in another process started by your GUI which uses matplotlib as in the link above and stores the pixmap to disk and your gui loads whenever a new pixmap is ready. QFileSystemWatcher might help here to avoid polling.

LabView playing more than one sound at the time

I'm using event structure and want to do some like Launchpad.
Numeric keyboard have for each number added a sound.
Problem is, that when I press number example one, the program is waiting when the music stop play and next I can press example number four.
Is it possible, to play sounds from 3 key's at the same time using event structure ?
I put the files online here and added screenshots below. Block diagram:
Front panel:
Working Solution
I think I got this working much more easily than I expected using the Play Sound File VI under the Graphics and Sound -> Sound -> Output palette. That link is the 2011 documentation (couldn't find a more recent link), but it does not look like it has changed. The working result is shown below, with two different events handled by the event structure:
Key Down? event:
Stop Button event:
You may be fine without using the Sound Output Clear VI to the right of the main event loop, but having it there won't hurt.
It turns out that the Play Sound File VI does not block, so you can play multiple overlapping sound files. If you run into blocking on your machine (one sound file plays, then the next, and so on), let me know because I have another solution that might work.
A word on events
An important thing to understand is that events are handled in a queue. When you press keys, those key presses go in order onto the event queue. Each time your event-handling loop executes, it takes the oldest event out of that queue and processes it. The event structure in LabVIEW will only handle one event per iteration of your event-handling loop. On the next iteration, if events are still in the queue that your structure is set up to process, it will take the next-oldest one for that iteration and repeat.
Now, lets say that you want to do some super complicated processing that takes 10 seconds every time you press a key, and you put that processing inside of your main event loop. Your key presses still go onto the event queue as fast as you press them, but LabVIEW has to wait the full 10 seconds before it can dequeue the next keypress and process it, so you end up with an application that seems to hang while it chugs through the queue much slower than you are adding items to the queue.
One way to get around this is to take that complicated processing and put it outside of the queue in another process. If you have the resources, you can actually call a separate instance of a processing sub-VI in its own thread for every one of those key presses. This allows the event handling loop to spawn processes as fast as you can press keys, and then your processes take whatever time they need to simultaneously (resources permitting) perform whatever actions you wanted.
Essentially that is what the Play Sound File VI is doing. It sees that you want to play a file and spawns a process to play that sound over the speakers, allowing the event-handling loop to continue immediately rather than waiting for the sound to finish playing. As you press more keys, more processes get spawn that kill themselves when they are finished. You can do this manually too, which is the other solution that I have for you if Play Sound File does not behave the same way for you as it did for me.
Update:
Thanks to #Engineero for pointing out that Play Sound File vi actually isn't blocking. The updated code shows how to play overlapping sounds. I'll leave it to the user to add the Stop Sound on Key Up code. No timeout is needed because nothing is taking place in the event structure.
Also, note that for me the Play Sound vi needed to be in a while loop to keep playing. Not sure why this is needed, but the NI examples sets it up this way (\examples\Graphics and Sound\Sound\Sound Player.vi).
Finally, you may crash the vi if your sound card gets overwhelmed as mentioned here. If that happens I would go with a better sound library to try and squeeze more performance out of your sound card.
Original:
First, I assume you a referring to this Launchpad?
I was able to press up to 4 keys at once will the following - the important thing is to set the event timeout to 1 ms. If you need more than that it will require a more sophisticated design.
I was no able to easily implement a sound because all the basic LabVIEW beeps are what's considered "blocking I/O" meaning if you call 2 Beeps simultaneously than Windows will play one after another not both at the same time. You will need to implement you instrument notes using non blocking I/O probably in a language other than LabVIEW such as this C++ library.

wxpython: wait for events mainloop freezes

I am new to wxPython, so please be gentle. I am trying to make a game using wxPython. I need to be able to handle events (button clicks) while the game is in progress.
The process is:
Deal the cards
Wait for user input
Continue accordingly
The way I have implemented it is:
app = wx.App()
g = Game() # calls g.Play() which executes the process above
app.Mainloop()
However the application freezes. I think the problem relates to being unable to respond to events while the process is being executed. How can I get around this?
I had a look at threading, but cannot see how to make this work in my case. If I create a new thread to deal with user inputs from within Game(), that will not be able to update the values in Game().
I am sure there is a "correct" way of doing this which I don't know because I am unfamiliar with wxPython. Can anyone help?
Yo do not need a seperate function play() to run the game. Just set up the event handlers to compute the state of the game during every event which results in a move of the game.
A good option would be to define a game state as say the cards in each players hands, and the turns that have been played and the scores, all defined as an object of a state class.
Chalk out an outline of how your game's architecture first. And you might also want to take a look at some examples and documentations on wxPython if you are new to it.
wxPython (and all GUI toolkits) are event driven. What this means is that they all wait for the user to "do something", like press a button, move the mouse, press a key on the keyboard, etc. When the uses does one of these things, wxPython checks to see if any of those events are bound to an event handler. If they aren't, wx will usually ignore the events.
You can learn about how to bind events properly here:
http://wiki.wxpython.org/self.Bind%20vs.%20self.button.Bind
So when you start the program, it should probably deal the cards at the start or possibly prompt the user to see if they want to start a new game or possibly continue a game. After that, the application would wait for the user to "do something". If the user executes a process that takes a long period of time (like a complex calculation, downloading a large file, etc), that process should be put into a thread. If you don't put it into a thread, then that process will block the UI's main loop and your app will freeze. See the following articles for information about wxPython and threads:
http://wiki.wxpython.org/LongRunningTasks
http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/
I hope these links help you on your way.

How can I perform actions while waiting for vertical sync?

I want to be able to load/download a bunch of resources and notify the user of the file that's currently being loaded, but I can't just draw a frame after each file starts loading because v-sync will wait until it can draw a frame before it continues (bottle-necking the loads to less than 60/second).
Is there a way to check whether the device is ready to draw or not (without hacky "has 1/60th of a second passed yet?), so I can perform actions until it's ready? I don't mind if the notification skips over files that finished before it's ready to draw, but I want to maximize the speed of the loads while still being able to notify the user.
Also, I'd like to avoid disabling v-sync even temporarily because I don't want to cause a graphic card crippling 300FPS rate if the computer loads really quickly.
You don't specify which version of Direct3D you're using. With D3D9 you can pass D3DPRESENT_DONOTWAIT to your Present() call and it will return D3DERR_WASSTILLDRAWING if the hardware is busy processing or waiting for a vertical sync interval. This means if you have vsync enabled, in your main loop you can just call Present with the DONOTWAIT flag whenever you've loaded a file and load another if it returns WASSTILLDRAWING.
Note that you need to get the swap chain and call Present() on the swap chain rather than calling Present() directly on the device to be able to pass this flag to present, or you can set it in the D3DPRESENT_PARAMETERS structure when you create the device or create an IDirect3DDevice9Ex instead of an IDirect3DDevice9 device and call PresentEx() instead of Present().
This doesn't solve the problem of files that take longer than a frame to load however - your frame rate will drop if you have a file that takes a long time to process. A better solution to this problem in my opinion would be to move as much of your IO as possible to another thread (in D3D9 you will still have to create D3D resources on your main thread however) and just pass the name of the file that's currently being processed to your main / render thread to display each time you present a frame.

Resources