SDraw – A drawing application for Desktop, written in C++ Qt
I started writing this application 5 years ago, because I wanted to improve my skills on customized widgets with Qt. I believe the current version of Qt at the time I programmed it, was 4.8. So now I have ported it to the current version of Qt which at the time of this writing is 5.7, corrected some bugs and put everything on
hoping that this will be useful for someone. There are still some bugs there that needs to be adressed to reach production quality, but it is good enough for demonstrating what can be done. A lot of the functionality is completed, but not everything. I can finish it, if someone wants me to. Feel free to leave comments in the comment section.
Here is a video explaining everything :
Now I will explain what you can do with this application. It looks like this :
Let’s begin at the top and work our way down. To begin with, there is a File Menu. It contains some basic actions for
- Loading an image
- Saving an image
- Print Preview
- Printing
- Exiting the application
Below the file menu, there is a toolbar that contains some action element. There is the save and load actions, corresponding to the items in the file menu, and there is a “New” action. If you click this action, you can see the “New Image” dialog in the picture above. It will let you choose image name, width and height. Clicking ‘OK’ will give you a canvas to draw on.
The central-widget of the application is a multiple-document-interface, on which you can have several canvases opened at the same time.
On the left-side of the mainwindow there is a toolbar with a separator. The content below the separator will depend on which item above the separator you have chosen. The items above the separator basically shows everything you can do in this application :
- Draw with a pen
- Fill with a brush
- Perform transformations
Now lets see which “drawing” options we have. If you have clicked on the ‘Pen’ icon on the far-left toolbar, you see the 3 different drawing options available below the separator. The first one is the pen-widget, which you can see in the picture above.
The dialog pretty much explains itself : You define the features of the pen that you want to draw with. As you can see, there is also a scripted demo on the bottom-right corner. It’s an “automated-artist” that draws a person, starting with head, then the nose, then the mouth and the finally the body (which is just a rectangle). The pen used to draw this person, is updated in realtime as you change different pen-features. And by the way, I did not make the color-wheel, this is a premade Qt-solutions-widget
The second pen–widget is for chosing what shape you want to draw :
Pretty self-explaining. The bottom option to chose the rounded-rectangle can be further defined by a custom widget to define angles. You can click and drag to change the degrees, the value in the spinbox will change accordingly, and vice-versa.
The last pen-widget just contains an options to switch anti-aliasing on and off.
Now, let’s explore the brush-widgets. So if you click the brush icon, which is the second action (from the top) of the far-left toolbar, you’ll see that the items below the separator change into options that are relevant for the brush. It doesn’t have a ‘shape’ widget, because that doesn’t make any sense in this case. Instead, it has a brush-editor.
In the middle, there is the ‘patterns’ groupbox. It will let you chose a pattern used for filling. If you change the color on the color-wheel above, the content on the buttons will be redrawn to reflect the change. The 3 items on the bottom-right side in the patterns groupbox are for gradients. If you click on the ‘linear-gradient’ button for example, the gradient editor on the top will get active. You can use it to specify a gradient. Do you see the upwards-pointing arrows below the ‘gradient’strip’? You can drag them left or right to set where you want the colors. Clicking an arrow will make it active, the active arrow will receive the color from the colorwheel. You can also edit the transparency of the color, by changing the value in the ‘Alpha’ groupbox. Making a color transparent, or partly transparent will make the background of the gradient-strip show. You can edit the spacing of the background grid in the ‘background’ groupbox. Playing around a little with the brush-widget could make it look something like this :
As you can see the sub-widgets are redrawn each time you change something, so that you can get a feel how it will look like when you draw. The bottom-right widget (in the gradient-spread groupbox) will let you set which angle to start from if you want to make a conical gradient.
Below you can see that I have drawn a rounded rectangle with a green pen which I filled with a radial gradient, and an ellipse with a brown pen filled with a linear gradient. Notice also that the ‘undo’ and ‘redo’ buttons became active. Every operation that you perform is actually it’s own object with a tiny image containing only the bounding rectangle of the drawn content, and the drawn content itself. These objects are stored in a stack (QMap). Undoing and redoing means pushing and popping on this stack. What you see is on the canvas are all these items drawn according to their geometry relative to the canvas, on a white background.
You can zoom by holding Ctrl-button and moving the wheel on your mouse, and pan by holding shift and moving your mouse. The zooming will zoom ‘towards’ the current position of the cursor above the canvas.
Now that we have seen how you can define a brush, then pen and we have drawn something, let’s explore the last option above the separator : transformations. Clicking this item reveals just a single item below the separator, the transformation-widget-action.
The ‘shape’ groupbox will let you choose how you want to define the region-of-interest (ROI) on the canvas. The polygon-option is only partly implemented so it’s very buggy. The free-option is not implemented at all, but would be almost the same as to define a polygon. Hence I will explain only the rectangle-option.
You can define ROIs by dragging on the canvas. You can have more than 1 ROI, as many as you want. Each ROI has 9 small boxes that you can drag to change the geometry of the ROI. A blue border on the ROI means it is active. You can deactivate it by clicking it, which will make the border gray. Reactivate by clicking it again. To delete a ROI, hover above it with your mouse and press the Delete-key. Performing a transformation on a ROI, inflicts all active ROIs :
Here you can see that both the ROIs was translated. As you can see, the original content of the ROIs was also left in its original position. This is what I have the ‘clone’ option for, but in this case it is actually due to the fact that the implementation is not completed.
Let’s try another transformation :
Here you can see I have deactivated the bottom ROI, and made the upper one bigger by dragging on the small boxes on the border of the ROI. Then I have chosen the ‘rotate’ option from the transformations widget. You can also select which axis to rotate around. You perform the rotation by click-hold-moving the mouse when you have the cursor inside a ROI. Following the rotatio- transformation, I did a scale-transformation to make the content larger.
The rest of the options I will leave for you to explore.
Summary
The sourecode for this project is available on
I used the following setup to port :
- Windows 7 computer
- Visual Studio 2013 Ultimate
- Commercial Qt 5.7 – x64
You can use it as you wish. For me, this project was something I worked with on my sparetime, even before I created the Broentech company to improve my skills on Qt and C++. Looking at the code now, I see that I do not necessarily agree with myself 5 years ago. There is definitely room for improvements and optimizations.
There was not really any commercial agenda behind it. Now I just hope it can be useful for someone else. Feel free to ask any question in the comment section.