Adding lines and shapes to a QML display?
As many of you who have been assisting me know already, I'm coding a simulator for an ASIC. I'm ready to explore making the UI look a little like a circuit drawing. For the unfamiliar, this means I need to draw lines, arrows, circles (some filled, some not), "+" and "x" signs. Most of these will be completely static for a given display and convey no content. It's debatable whether any of the shapes will be complex enough to warrant re-use, but...I'm open to that.
It looks like I can do a lot of what I want with Designer, but...before I get started down that path, I thought I'd ask if there's a preferred way for "drawing" diagrams within QML.
At this point, I should probably tip my hand and mention that eventually, I'm going to want my UI to be able to "zoom;" that is, it would begin with a top-level diagram, and clicking on a component would take you to a drawing of that, exposing more detail. I don't need to know how to do this now, but I thought I'd mention it, since it might influence the desired implementation technique.
Thanks for any help.
The approaches typically suggested tend to fall into the broad categories of 1) develop some custom QDeclarativeItem-derived components, or 2) try a canvas-based approach. Here are a few previous discussions that I think touch on the issue:
Hmm...judging from the dates on some of those posts, I guess this is a rather fluid area right now.
Would I be better off doing this outside QML (choosing a different approach for the GUI)?
If you feel that QML is not suited to your current needs then you could also take a look at using QGraphicsView. This is very similar to creating custom QDeclarativeItem-derived items except that you instantiate them in C++ too.
Hi, Zap -
I didn't mean to imply that QML wasn't suitable; if anything, I thought it might be overkill. When I compare what I want to do to some other QML programs, my needs seem pretty trivial (so far, anyway).
Here's a drawing of something I pulled off the web that's akin to what I'd like to do:
A few of the rectangles would contain numeric values that would be updated, possibly using the techniques you guided me through in an earlier thread. The rest would be static.
Does QML seem like the preferred tool for something like this?
Yes it is certainly feasible to do this with QML. One approach would be to simply load in the static part of the image from an SVG for example. You could then overlay Text elements on top of the background image at carefully chosen coordinates. You already know how to bind the text property to a property of a QObject-derived object.
That is a simple but rather hard-coded approach. A better way (especially if you have many reusable components) would be to apply the above to each component. For example you could define a QML Component for IC-555 from the above example. In this component you would again have a background image and some Text elements but they would all be specific to that IC. You can also expose the text property of each Text element as a property of your IC-555 Component and give them a sensible name perhaps related to what that particular pin of the IC is for.
Then you have a nice reusable component that can be instantiated and positioned in your scene as many times as you like. Rinse and repeat for as many other components as you need.
The same kind of thing can also be done entirely within QGraphicsView but QML is probably quicker and less hassle.
So, if I understand you, you're suggesting to create some "template" components to re-use in my display(s)? Sort of like classes and objects?
If this is correct, how would it be implemented? Would I create another .qml file to contain these, and somehow reference them in my "working" .qml file? I'm not trying to get overly fancy; just understand the mechanism. I can see how to add background images through Designer, but I think that would be more "hard-coded" than you're suggesting.
Would I use images for things like the arrows and lines, too? That seems like a bit of a hassle, but...I can't figure out how I'd create arrows in QML.
Personally, I think I would not go for QML for an application like this. Instead, I'd use a QGraphicsView. Then, for each type of component, I would create a GraphicsViewItem, that can be instantiated using a factory and that displays the relevant data for itself.
Just got back to this...so, I'm viewing/editing my widget.ui file, and I found the "Graphics View" widget. Is this what you're talking about? Looking at its properties, it isn't clear yet how I'd use this to, for example, create a solid line for the display. It would be great if I could get a little more direction on how I should use this.
Snooping around the docs, I did find the QLineF object. Am I on the right track here? If so, how do I go about creating one of these? I don't see it in Design mode, and I can't manually edit the .ui file.
Yes, the QGraphicsView is the widget you can use for displaying graphic scenes. You are going to need a QGraphicsScene to put your items on, and set that scene on your view. Just like the models in the model-view you use for lists, tables and trees, a scene can be displayed by more than one view at a time. Onto your scene, you put QGraphicsItem instances (or, usually, subclasses of that class). For drawing a straigh line, you would use QGraphicsLineItem, for instance, and for drawing a box, you would use QGraphicsRectItem. Each item can have child items, so you can make composite items. In your case, i would make composite items for every type of component you have to deal with. These composites then can draw the shape as well as the needed text items at the appropriate places on or around the shape.
This drawing on the scene can not be done at design time. You do that in code.
QLineF is something different. It is not related to QGraphicsView.
Another approach that making composite items is to create your own custom classes derived from QGraphicsItem or from QGraphicsObject (if you need signal/slot support) or from QGraphicsWidget (if you need signal/slot and layout support).
In your custom item class you should override the paint() function and the boundingRect() function (except if you inherited QGraphicsWidget where you instead need to override the size hint related function). In your paint function you can use QPainter to draw whatever you like as long as you stay within the rect that you specified in your boundingRect() function. That way you can draw and arrow for e.g. in a single item rather than requiring 3 items (and 3 calls to paint()).
Incidentally this is almost exactly the same as making your own custom QML items. Instead of deriving from QGraphicsItem you derive form QDeclarativeItem (which in turn derives from QGraphicsItem). Then you can instantiate your custom items in your QML scene.
I spent a big part of today looking at SVG editors for the Mac. (Everywhere I go, I find a new technology that I need to learn about!) I found one that looks pretty easy to use (DrawIt), but I'm not sure it generates .svg files. I'll have to check with their support group.
Once I become comfortable with my ability to generate suitable .svg files, I'll come back and ask questions about embedding them into a QML object (if that's the right terminology). Thanks, guys.
Take a look at inkscape. It is cross platform, but they seem to be "allergic":http://wiki.inkscape.org/wiki/index.php/FAQ#What_language_and_toolkit_is_Inkscape_built_upon.3F to Qt. Still, I think it is pretty good.
Inkscape is as ugly as tobacco subsidies. The UI makes me feel like I'm back in the 1980s. I'm going to try to find something -- anything -- else.