I have a python program where I have several matplotlib canvases embedded into a wxpython application. One of the canvases has many crosses in it. When the user right-click in this canvas the closest cross should be removed together with everything belonging to this cross (they are linked through an unique id-tag, and there might be things in every canvas that should be removed). I want the removing (or actually the replotting) to be as fast as possible. The program is quite large so I use several threads etc.
The easiest thing to implement this is to use wx.CallAfter(canvas.draw) for each canvas. However, there is a delay between the rightclick and the refresh of every canvas so I believe that canvas.draw() is too slow.
I saw two other functions for fast redrawing: the matplotlib functions blit() and draw_artist(). As far as I understand, blit() refreshes changed pixels inside some area (I used the axes bbox). I managed to get it to work with blit() in the sense that the program ran without crashing...but not updating what you see on the screen.
Did not manage to get draw_artist() to work when removing a pixel (tried using first line.remove(), then draw_artist(line) but the line was ofcourse already dead so draw_artist did not work).
Note: I called blit() and draw_artist() with wx.CallAfter()!
The feeling I have is that blit() is the best solution, but I did not manage to get it to update to the "screen-level". So my question is: what is the fastest and most resource-saving way of removing artists from matplotlib.canvases (embedded into wxPython) without redrawing more than you need to, but still let the change propagate to the screen?
Related
I am writing a kicad plugin, and I need to create a GUI for this plugin. Because kicad uses wxpython, that is what I am using.
I have already figured out that placing my ui items using the layout sizers just isn't gonna give me the control I need to create the window I want. I know I can set the position of elements, and have been using that to create the ui I need.
The problem however, is that my window gets bigger than what would be reasonable (in some situations). Therefore I want to make it scrollable.
I have been playing around with wxformbuilder, and I found the wxScrolledWindow. That got me this far:
This is roughly what I want, except, when you want to place stuff within the scrolledWindow, you have to place one of the "sizers" in it (as far as I can tell at least), in which you place your buttons. The problem with that is, that, to my knowledge, setting the position of buttons in any of the sizers just has no effect at all.
So, my question is: how do I achieve this effect? and, is this even possible?
edit:
As an example of what I am trying to put within the scrolledwindow, this is a rough version of the ui I want to create (and want to be scrollable). (I want to eventually have, probably an icon button above each of the checkbox columns to indicate what they are for).
The final result would need to look something like this (the white squares being small images / buttons, also, in reality being not on the window bar,but in its own not scrolling section):
An example of something I wasn't able to achieve using sizers is, getting those checkboxes so close together, without making them appear off center. Different widgets seem to have different sizes, and checkboxes without border are especially small, so they end up appearing off center, example:
Also, those images above each column of checkboxes, which don't scroll, need to line up with the X coordinates of those scrolling checkboxes, which also seems very non trivial. Though also really hard to get right if I could give everything exact coords, so I might need to give up on that specific idea of making those not scrollable.
I am pretty new to Python and coding in general. I have been working on a program that is similar in nature to ms paint. So far, I've added the capabilities to create multi-colored rectangles, lines, ovals, and really any polygon.
I've been using the tkinter GUI. I've been wanting to add a fill command, but I'm kind of stuck as to how to start it. My idea for how it would work would be that it would check the color of the pixel the user is currently hovering over, then check up, down, left, and right for the same color in pixels. If it found that, it would change the color of those pixels (I guess by creating a really small rectangle object?). This would theoretically be able to fill an area. But, I really can't find anything on how to access the color of a pixel in tkinter.
I know the location is event.x and event.y for a specific event, but I can't find anything about pixel color. I don't really have any code written for it yet because I am unsure that tkinter can even access the color of a pixel and not just object colors.
Unfortunately, this isn't possible. I did some searching around, and found several other similar questions, but the general idea is that Tkinter does not support such a feature. It makes sense, considering that Tkinter is a GUI library.
I saw a suggestion somewhere, where an idea was proposed to create 1x1 rectangles using the Tkinter Canvas to basically mimic pixels. However, this method eventually leads into performance issues and lagging, so it's not really recommended either.
You may want to try exploring some other libraries to work together with Tkinter. You can keep the Tkinter GUI, but use an image manipulation library or something similar which integrates well with Tkinter, for the actual pixel drawing.
I have a custom object(a small circle) placed at some point inside a Gtk.Fixed() widget .Is there a way to drag this object around using the mouse. I am not able to map the Mouse Press/Release/Motion events to make this work.
I would prefer solution in Python using PyGobject but any other language will do also be fine if explanation is provided
More Details:
I am trying to make a font editor where these objects I mentioned above will be the control points of the bezier curves in the Glyph outlines
Here is an image of the concept design:
https://github.com/sugarlabs/edit-fonts-activity/blob/gh-pages/files/img/wireframe_concept_01_first_prototype.svg
I need to able to move the points shown to edit the outline of the letter shown
GtkFixed is not designed to do drawing work. It's made to locate widgets (such as buttons and such) on a fixed grid (รก la Windows).
If you would like to move elements of a drawing, have a look at eg. GooCanvas. Each element on a goocanvas can have events connected, which can then be used to move it around. You can even use CanvasGroup to group primitives (circle, rectangle etc), and move them together (even change other properties such as color, linewidth). The toolbox actually contains curves etc. It's easy to create a 'handle' using a small rectangle.
Here's an example of a simple goocanvas program, and you can find download links, references manuals and other useful stuff here.
I don't know if this is a tool you need, or just a learning exercise. If the former, then do have a look at FontForge, an open source font editor, and incredibly versatile.
I'm having problems getting my wxPython window to refresh. It's currently plotting a graph using wxmpl which can be zoomed, panned, etc. On occasion the user may plot a large amount of data and zoom in on a small portion, which can cause it to 'freeze up'. By that I mean the plot itself is not updated, and the axis labels are drawn on top of each other. It is modifying the plot, just not displaying the updated info correctly. If you resize the window the plot is redrawn correctly.
I've spend an inordinate amount of time digging through source code and documentation for wx, wxmpl, and matplotlib... The best solution I've come up with is resizing the window to force a repaint (thus displaying the updated plot correctly).
# All of these fail - displays the same, incorrect plot
# (view is a wxmpl.PlotPanel object, which inherits from wx.Window among other things)
view.Refresh()
view.Update()
view.draw()
# This works, but is clearly less than ideal
view.SetSize((view.GetSize().width, view.GetSize().height+1))
view.SetSize((view.GetSize().width, view.GetSize().height-1))
There's got to be a better way - what I really want to know is what wx.Window.SetSize does to redraw the window, and just call that instead. Or, is there another method that I missed somewhere?
The panel.Layout() command is a great option because it is exactly the same method that is called when you resize your window. I also had trouble with the refresh and update methods. Layout seems to work when those two fail.
If you can't place it anywhere else, you could try
wx.Yield()
instead of Refresh or Update.
I would also try Show(False) and then Show(True) on the PlotPanel.
In a computational expensive application, where you are expecting something to be calculated for over 0.1 sec and probably have some user input it is not recommended usually to make those intense drawing in the GUI thread.
Not aware of your specific situation, but general approach if that you move all time consuming tasks (be it computation, image adjustment (e.g. scaling)) to the non GUI thread. Just a normal Python thread is fine, and once you have an long part complete, you refresh your GUI. During computation of course it would be a user friendly to display some sort of "waiting" sign. Also disable other controls, so bored user will not be able to change anything midway to your computation.
I was stuck with that issue since my early days with Java and later with Python, mostly in connection to network operations (which NEVER should be in GUI thread).
In case it is image adjusment (or graphics generation), which takes much time, background thread can prepare image in wxMemoryDC and then wxDC::Blit it to the window of your choice. I am not aware if this can be done with your component wxmpl.PlotPanel, so you will have to research this.
I'm writing an application for the Maemo platform using pygtk and the rendering speed of the tree view seems to be a problem. Since the application is a media controller I'm using transition animations in the UI. These animations slide the controls into view when moving around the UI. The issue with the tree control is that it is slow.
Just moving the widget around in the middle of the screen is not that slow but if the cells are being exposed the framerate really drops. What makes this more annoying is that if the only area that is being exposed is the title row with the row labels, the framerate remains under control.
Judging by this I'm suspecting the GTK tree view is drawing the full cells again each time a single row of pixels is being exposed. Is there a way to somehow force GTK to draw the whole widget into some buffer even if parts of it are off screen and then use the buffer to draw the widget when animating?
Also is there a difference between using Viewport and scrolling that up and using Layout panel and moving the widgets down? I'd have imagined Viewport is faster but I saw no real difference when I tried both versions.
I understand this isn't necessarily what GTK has been created for. Other alternative I've tried is pygame but I'd prefer some higher level implementaion that has widget based event handling built in. Also pygtk has the benefit of running in Windows and a window so development is easier.
I never did this myself but you could try to implement the caching yourself. Instead of using the predefined cell renderers, implement your own cell renderer (possibly as a wrapper for the actual one), but cache the pixmaps.
In PyGTK, you can use gtk.GenericCellRenderer. In your decorator cell renderer, do the following when asked to render:
keep a cache of off-screen pixmaps (or better, just one large one) and a cache of sizes
if asked to predict the size or render, create a key from the relevant properties
if the key exists in the cache, use the cached pixmap, blit the cached pixmap on the drawable you are given
otherwise, first have the actual cell renderer do the work and then copy it
The last step also implies that caching does incur an overhead during the first time the cell is renderered. This problem can be mitigated a bit by using a caching strategy. You might want to try out different things, based on the distribution of rendered values:
if all cells are unique, not much to do than caching everything up to a certain limit, or some MRU strategy
if you have some kind of Zipf distribution, i.e. some cells are very common, while others are very rare, you should only cache the cells with high frequency and get rid off the caching overhead for rare cell values.
That being said, I can't say if it's going to make any difference. My experience from a somewhat similar problem is that anything involving text is usually slow enough that caching makes sense---sorry that I can't give simpler advice.
Before you try that, you could also simple write a decorating cell renderer which just counts how often your cells are actually rendered and get some timing information, so that you get an idea where the hot spots are and if caching the values would make any sense at all.