Issue with updating webpage GUI - python

I have a django site which is going to display various matplotlib plots. I am able to create a matplotlib plot, convert it into a png and display it,...but only if all the logic is contained within the views.py file of the relevant app.
This would be fine if I just needed a fairly basic page with a simple plot. However the problem is that the site as a whole is going to require several plots each involving their own python files, logic etc.
So what i've done is created a new folder within the app that contains the python files for calculating the various plots. From within the view.py I was planning on just calling the relevant python file which would return the plot. By doing that, I could keep the logic around how the plots are created separate from the displaying of the page.
The problem that i've run into is the following error
QPixmap: It is not safe to use pixmaps outside the GUI thread
After researching this error it is clearly and issue when you are trying to update the GUI from a different thread. However that is not what im trying to do. Im trying to create the plot outside of the views.py file, then pass it back and create the png to update the page. So the updating of the GUI shouldn't be happening in another thread?
My code in views.py is:
fig = plotLogic.getPlot() #this is a call to a separate file which returns the figure
canvas=FigureCanvas(fig)
response=django.http.HttpResponse(content_type='image/png')
canvas.print_png(response)
return response
Is there an alternative way to accomplish what im trying to do? Essentially just keeping the logic of how the plot is created separate and returning the plot so that it can be converted to a png and displayed.
I feel like I am somehow making this more complicated than it should be. Im not intentionally trying to do anything fancy like updating the GUI in a separate thread.
Many thanks.

Related

How can I use one program for graphics and one program for processing?

What I'm doing is creating a model of a football field, which has a lot of code simply because there are a lot of parts to a football field. This code is more than 300 lines long. This is quite annoying to scroll through, and I don't want to put it at the end of my code since I might have to go back and edit it, which brings back the scroll program. The rest of this program will be processing sets of coordinates on the field and creating movement animations. Is there any way I can split this into two separate files, one that is just the graphic side and the other that is the processing side?
Yup!
Put code you want to seperate into new graphics.py file (functions, class, etc)
Add import to top of your main file (from graphics import graphics_object)
Run it, and if your imports and separation were right, it should run the same.
See also:
https://www.w3schools.com/python/python_modules.asp

Pyqt5/Pyside application with Ipywidgets and Interactive figures

I’m building a GUI (pyqt or pyside) to easily create complex figures (e.g. with plotly) for users.
So far so good, I run the data processing and produce plotly figures that are exported as html and read by QwebEngineView. I even created a qt widget for layout editing by the user (see image below).
The problem with this is the long delay (few seconds) in the process of:
updating the layout -> exporting to a temp html file → open and rendering the file on GUI.
I want to make a better GUI experience with layout editing.
Following this great Jon Mease talk I discovered my plotly figures could be updated in real time using the also great ipywidgets, but only on Jupyter notebooks / lab environment. That is, exporting the widgets+figure to a html file renders all elements, but since the python backend will be lacking for the widgets (in the standalone html file), they won’t interact with the figure’s layout.
However, my application IS running on a python process, so I have the feeling this should be a solvable problem somehow...
Qtconsole won’t render ipywidgets, so I can’t use it to expose my figures in the GUI.
Voila renders Jupyter notebooks with interactive widgets, I’m not sure however if I could access it and incorporate it to the GUI. It says it can work both as a “standalone tornado application” or as a “server extension to notebook or jupyter_server”.
I’m aware there’s probably not a final solution to that, but I would appreciate any suggestions on how to approach this problem! Thanks!
I ended up creating a solution for the problem: QtVoila
It is basically an extended QWebEngineView that manages and renders a Voila process, with some extra functionalities.
Here's a blog post explaining it:
https://www.taufferconsulting.com/portfolio/qtvoila

OpenCv Video Display PyQt5

I'm working with opencv3, python 3 and pyqt5. I want to make a simple GUI in which I want open up a new window to play a video along with some other widgets when a button is clicked on the main window. I've used QPixmap for displaying images in the past so I create a label and try to set the frames in the pixmap in a loop. The loop works fine but I am unable to get a display of the video/new window.
The loop I want to execute in the new window looks something like this:
def setupUi():
vid=cv2.VideoCapture('file')
ret, frame=vid.read()
while ret:
Qimg=convert(frame)
self.label.setpixmap(Qimg)
self.label.update()
ret,frame=vid.read()
convert() is a function I've written myself that converts the cv frame to QImage type to be set into the pixmap.
I'm only a beginner with pyQt so don't know what I am doing wrong. I've read about using signals, threads for the new window and QtApplication.processEvents() but don't know how these work and how they'll fit into my problem.
It would be helpful if someone could set me in the right direction and also point out some resources to create good interfaces for my apps using OpenCV and python.
The reason that this isn't running is that your while loop is blocking Qt's event loop. Basically, you're stuck in the while loop and you never give control back to Qt to redraw the screen.
Your update() call isn't doing what you think it is; it's updating the data stored by the object, but this change does not show up until the program reenters the eventloop.
There are probably multiple ways of handling this, but I see two good options, the first being easier to implement:
1) Call QApplication.processEvents() in every iteration of your while loop. This forces Qt to update the GUI. This will be much more simple to implement than 2).
2) Move the function to a separate class and use QThread combined with moveToThread() to update the data, and communicate with the GUI thread using signals/slots. This will require restructuring your code a bit, but this might be good for your code overall. Right now the code that is generating the data is in your MainWindow class presumably, while the two should be kept separate according to Qt's Model-View design pattern. Not very important for a small one-off app, but will help keep your code base intelligible as your app grows in size.

How to update existing matplotlib (python) figures with sublime text

I've been using the IEP from pyzo before trying out Sublime Text (ST).
There is an annoying behaviour with ST that IEP doesn't have.
In IEP, much like with Matlab or Octave, the editor and the interactive console talk to each other.
Typically if you compute some_stuff and plot it in a script, after execution of this script you can go to the console and check some values:
print some_stuff[0:10]
or modify your plot:
plt.whatever()
which will update your figure.
Also if you run your script several times with different parameters, the figure is simply updated.
However when you do so in ST, even with REPL, after execution of the script nothing is left, you can't access some_stuff[0:10] from REPL. Similarly, you can't modify your figure. And if you run your script several times with different parameters, a new figure is generated in a new window each time instead of updating the existing figure.
Is there an easy work around this? Thanks!
How about saving your figure to a file with plt.savefig("fig.png")? If you open that file with your image viewer it will be updated after running your program.

How to advance to a "new page" using pygtk?

I'm new to programming in python, but I've went through tutorials which taught me how to create click-able images and connecting them to trigger a callback function.
I am trying to write a script which will allow me to click an image, and move onto a new window or "page" of different click-able images.
Is there a way for me to do this using pygtk? I thought about creating classes and using an if else statement to poll through classes I wanted to use, but it hasn't worked for me. Or am I suppose to continuously hide and show buttons and images?
Is there a way to modify the sample code I've been using to accomplish my goal?
http://pygtk.org/pygtk2tutorial/examples/images.py
Any help would be appreciated, thanks!
You can use a GtkNotebook and hide its tabs. Whenever you need to change page, just switch the current page of the GtkNotebook.

Categories