Jump to content
hauschka

.py communication with .qml for printer status plugin

Recommended Posts

Posted · .py communication with .qml for printer status plugin

Dear Cura plugin community,

 

I would like to build an addon, with which I can display the printer's status and printbed temp within the "Monitor"-Tab.

So far, I can query my printer via Wifi and get a json-style response via QNetworkRequest. However, since I am unfamiliar with Qt and QML, I am having troubles parsing this data to a Label within MonitorMain.qml

 

So far, I have:

 

MonitorStage.py:

class MonitorStage(CuraStage):

[...]

   def Response(self, reply):
    [...]
    response  = json.loads#Here I get the json from the printer

I'm having a hard time with Qt's signal/slot system, where I'm struggling to parse a value from the response to a QLabel in MonitorMain.qml

 

 

Would any of the more seasoned programmers on this board be able to point me to the right directions?

 

Best regards,

hauschka

 

Share this post


Link to post
Share on other sites
Posted · .py communication with .qml for printer status plugin

Well, you shouldn't add it in the monitor stage directly, that's for one. The monitor stage is intended to display data that it gets from 
a "PrinterOutputDevice" (or in your case, probably the "NetworkedPrinterOutputDevice")
As you may know, Cura has a pretty extensive plugin system. Both situations that also do what you want are the "UM3NetworkPrinting" plugin (bundled with cura) and the OctoprintPlugin (https://github.com/fieldOfView/Cura-OctoPrintPlugin).

So what needs to be done is that you create your own version of the printerOutputDevice / NetworkedPrinterOutputDevice (by means of inheritance) and ensure that the properties / functions that it exposes are filled with the correct data.

A bit more general info on Qt/QML to make the code a bit more understandable; Qt heavily relies on properties (pyqtProperty), signals (pyqtSignal) and slots (pyqtSlot). Properties are essentially attributes, but with one major exception; they have the "notify" ability. When you use a property in QML and the property is changed on the python side, you can notify the QML that this happend by emitting the right signal (signalling the change, hence the name).  Lets look at a bit of code:

@pyqtProperty("QVariantList", notify=printJobsChanged)
def printJobs(self) -> List[UM3PrintJobOutputModel]:
  return self._print_jobs

First of is the bit that starts with the @ sign. This is a decorator, which is a pretty nifty built in feature of python. What it essentially does is taking whatever is below it and modify it (eg "decorating it"). In this case, it's turning the function into a property that is also exposed to QML. The first parameter is the return type (A list of QVariant) and the second one is telling it what signal is emitted if the value is changed. You can either set the "notify" or you can set "constant=True" in which case you indicate that the value will never change once set.

Slots on the other hand are what Qt calls exposed functions. So all functions that are decorated with the pyqtSlot are functions that can be called from QML. They use a similar pattern as the properties.

@pyqtSlot(QObject, name="setActivePrinter")
def setActivePrinter(self, printer: Optional[PrinterOutputModel]) -> None:
  if self.activePrinter == printer:
  	return
  self._active_printer = printer
  self.activePrinterChanged.emit()

The first parameter of the decoration is the first parameter accepted by the function (so the printer parameter). The name is set as this is usefull for debugging. Finally, you could also set the "result" parameter, which indicates the return type of the slot (if any).

  • Like 2

Share this post


Link to post
Share on other sites
Posted · .py communication with .qml for printer status plugin

Dear Nallath,

 

Thank you do much for this thorough answer. I certainly wasn't expecting this amount of detail.

 

I have been looking into ahoeben's (fileofview) Octoprintplugin, especialy how he accesses the PrintMonitor part.
However, since I'm unfamiliar with the inner workings of Cura, it raised a lot more questions, which is why I reverted to not "reusing" Cura's internal features, but just redrawing GUI elements in the MonitorStage and feeding it with values.


Needless to say, that's apparently not the way to go 🙂
 

 

@nallath, thank you so much again for clarifying this situation! I will a take a more in-depth dive into Cura's code and figure out how

all the componenets work together.

Is there by any chance a graphic/description that details how Cura's set up internally, that I missed?

 

Al the best,

-h

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

Welcome to the Ultimaker Community of 3D printing experts. Visit the following links to read more about our Terms of Use or our Privacy Policy. Thank you!