Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Example code for a minimal paint program (MS Paint style)

I want to write a paint program in the style of MS Paint.

On a most basic level, I have to draw a dot on the screen whenever the user drags the mouse.

def onMouseMove():
    if mouse.button.down:
        draw circle at (mouse.position.x, mouse.position.y)

Unfortunately, I'm having trouble with my GUI framework (see previous question), I'm not getting mouse move messages frequently enough. I'm using the GUI framework wxWidgets and the programming language Haskell.

Question: Could you give me some example code that implements such a minimal paint procedure? Preferably, your code should be use wxWidgets, but I also accept GTK+ or Cocoa. I don't mind any programming language, as long as I can install it easily on MacOS X. Please include the whole project, makefiles and all, since I probably don't have much experience with compiling your language.

Basically, I would like to have a small example that shows me how to do it right in wxWidgets or another GUI framework, so I can figure out why my combination of Haskell and wxWidgets doesn't give a decent frequency of mouse move events.

like image 749
Heinrich Apfelmus Avatar asked Jan 22 '23 14:01

Heinrich Apfelmus


2 Answers

For Cocoa, Apple provides an example named CIMicroPaint, though it's a bit complicated in that it uses Core Image instead of Quartz 2D. Here a screenshot: CIMicroPaint screenshot

like image 82
Heinrich Apfelmus Avatar answered Jan 31 '23 12:01

Heinrich Apfelmus


I know this is an old question but nevertheless - in order to get smooth drawing, it is not simply enough to put an instance of your brush at the location of the mouse, as input events are not polled nowhere nearly as fast as they need to for smooth drawing.

Drawing lines is a very limited solution as lines ... are lines, and for a drawing app you need to be able to use custom bitmap brushes.

The solution is simple, you have to interpolate between the previous and current position of the cursor, find the line between the two points and interpolate it by adding the brush for every pixel between the two points.

For my solution I used Qt, so here is the method that interpolates a line between the last and current position in order to fill it out smoothly. Basically it finds the distance between the two points, calculates the increment and interpolates using a regular for loop.

void Widget::drawLine()
{
    QPointF point, drawPoint;
    point = newPos - lastPos;
    int length = point.manhattanLength();
    double xInc, yInc;

    xInc = point.x() / length;
    yInc = point.y() / length;

    drawPoint = lastPos;

    for (int x=0; x < length; ++x) {
        drawPoint.setX(drawPoint.x()+xInc);
        drawPoint.setY(drawPoint.y()+yInc);
        drawToCanvas(drawPoint);
    }
}

This should give you smooth results, and performance is very good, I have even tested it on my Android tablet which is a pretty slow and laggy device and it works very well.

like image 38
dtech Avatar answered Jan 31 '23 10:01

dtech