Can I change the image displayed on screen with a slider? - c++

I want to use the value output by this slider to change the image which is loaded into the img variable. The paint function is called whenever the slider is moved.
The slider's value is 0 - 2. The second if statement tests as correct when the slider is > 1, however, the image does not change. Without the if statements I can switch the image manually, otherwise it isn't doing what I expect.
void ModelGUI::sliderValueChanged(Slider* slider)
{
rotate.getValue();
DBG(rotate.getValue());
}
void ModelGUI::paint (Graphics& g)
{
DBG("PAINT");
g.setColour(Colours::red);
if(rotate.getValue() < 1)
{
img = ImageFileFormat::loadFrom(f);
}
if(rotate.getValue() > 1)
{
img = ImageFileFormat::loadFrom(f2);
}
g.drawImage(img, model);
g.drawEllipse(225, 230, 2, 2, 2);
g.drawEllipse(240, 240, 2, 2, 2);
g.drawEllipse(245, 275, 2, 2, 2);
}
Why is this happening? Cheers

just a wild guess but shouldn't you force repainting in the sliderValueChanged event somehow? I do not know juce but I would expect one of these:
g.Repaint();
g.Refresh();
g.Update();
as changing slider is probably just repainting the slider itself and not updating the rest of your GUI. The g should be your Graphics object of coarse.
If the repaint is really time consuming then I usually do something like this:
bool _redraw=false; // some global variable (or local but accessible to your GUI/Form/Canvas whatever)
void any_event()
{
// here event stuff code
if (need_to_repaint) _redraw=true; // for example you change something hit a special key that changes something etc ...
}
void timer() // any timer with target max fps interval
{
if (_redraw())
{
_redraw=false;
// here force repaint or call the repaint directly
}
}
This way the repaint will not slow down other events too much. For example If I use zoom on wheel and I am rendering a lot of stuff the wheel could feel slagish if repainted on each change of wheel. This will repaint only with timer period which should be fine if set right.
The usual events that need such handling are zoom, mouse move/edit and window/view resize as they can create a lot of event calls per second ...

As #Spektre surmises -- in JUCE, your component needs to request that it be repainted when it knows that's necessary. In this case:
void ModelGUI::sliderValueChanged(Slider* slider)
{
rotate.getValue();
DBG(rotate.getValue());
repaint();
}
...will cause your ModelGUI component (and all of its child components) to repaint at the next reasonable point in time.
See: https://docs.juce.com/master/classComponent.html#af3ab3eabec93dd60faf983370f3a1206

Related

Some controls are not drawing, seemingly at random

I'm trying to write a little MFC app just for myself, to test some AI's I'm training.
So I added a picture control and a static control where I can paint stuff freely in the OnPaint() method of my main Window.
It seems to work when just drawing my app once, but I now added a loop that performs OnPaint() multiple times before stopping.
When in this loop, some other controls don't show up, for example all my buttons are gone, and some sliders even are missing some times, but other times, they're there.
My code goes like this:
void CKiUebung1Dlg::OnBnClickedButtongo()
{
m_bisGoing = true;
OnPaint();
if(m_fDiagramData.size() <= 0)
{
m_fDiagramData.push_back((float)rand() / RAND_MAX);
InvalidateRect(NULL, TRUE);
}
OnPaint();
for(int i(9); i >= 0; --i)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
m_fDiagramData.push_back((float)rand() / RAND_MAX);
InvalidateRect(NULL, TRUE);
OnPaint();
}
m_bisGoing = false;
OnPaint();
}
void CKiUebung1Dlg::OnPaint()
{
if(IsIconic())
{
CPaintDC dc(this); // Gerätekontext zum Zeichnen
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Symbol in Clientrechteck zentrieren
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Symbol zeichnen
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
{
constexpr const int border = 5;
CPaintDC dc(&m_cDiagram);
CRect l_cPos;
m_cDiagram.GetClientRect(&l_cPos);
const int width(l_cPos.Width() - border * 2 - 2), height(l_cPos.Height() - border * 2 - 12);
const int numPoints(m_fDiagramData.size());
POINT* points(new POINT[numPoints]);
for(int i(numPoints - 1); i >= 0; --i)
{
const int
x((float)i / (numPoints - 1) * width + border + 1),
y(height - m_fDiagramData[i] * height + border + 9);
points[i] = { x,y };
}
dc.Polyline(points, numPoints);
static CString going(_T(" "));
if(m_bisGoing) { going += _T("."); if(going.GetLength() > 300) going = _T(" ."); }
else going = _T(" ");
float fprog(0); if(m_fDiagramData.size() > 0) fprog = m_fDiagramData.back();
CString prog; prog.Format(_T("Progress %03.2f%%"), fprog * 100); if(m_bisGoing) prog += going;
m_cDiagram.SetWindowTextW(prog);
m_cDiagram.RedrawWindow();
delete[] points;
}
}
This is how it looks when the loop isn't running:
This is how it looks when the loop is running:
You seem to have trouble understanding how invalidating/painting works.
The documentation you should read first is:
Painting and Drawing
While many developers recommend painting only in WM_PAINT processing (OnPaint() in MFC), this is not always the best solution, because this message is low-priority, painting may not be immediate (have a "choppy" feel), and you may get a "flickering" effect.
Instead, I sometimes recommend a mix of drawing and painting:
Employ painting in WM_PAINT processing. This should paint the whole client area (or only the invalidated part of it, if you want a more "optimized" implementation). Please note that WM_PAINT message may be received as a result of invalidating a part or all of the client area, due to moving, resizing, unhiding etc the window, in addition to programmatically invalidating it. So in response to a WM_PAINT message you should perform a full repaint, ie all the items you want to be displayed.
Employ drawing for the changes you want to be shown immediately, while the application is busy (not waiting for the "asynchronous" WM_PAINT message to be received). Please note that these should be in WM_PAINT processing as well, so you rather have to write some drawing/painting routines, taking a HDC (or CDC*) as a parameter (along any other parameter needed), and call them from both the OnPaint() function (passing the ClientDC there) and from your additional drawing actions needed (passing a CDC* acquired by calling GetDC()).
So, let me share my experience with an application I wrote some (long) time ago. It's an image-display/manipulation (among others) application, processing images in a custom format, and using a special library, which was rather "slow", as it only provided a function to display the image in the device context (this includes possible cropping, adjustments, resizing etc which are CPU-costly operations). Here is an image:
You can see the user performing a selection. The application has to display the image, and possibly the selection rectangle on top of it, and of course that's what OnPaint() does. An "easy" (albeit technically "correct") implementation would be to call Invalidate() or InvalidateRect() in response each mouse move message (while selecting). This would cause a full repaint (which is "OK"), but also suffer from performance problems, due to the slow image-library: if you also call UpdateWindow() after invalidating (requesting an immediate refresh) performance would be sluggish (having to reprocess/redisplay the image), if not, the refresh would just take place some (noticeable) time later. This was solved by employing drawign (not painting) in response to the WM_MOUSEMOVE message: no invalidating there, instead drawing just the selection rectangle (after restoring the part modified by the previous selection message - I only backup/restore the four sides of the frame, not the whole rectangle). As a result, the application is responsive and the operation smooth, despite the slow library, and shows the image and the selection correctly, even if you switch to another application and then back to it, while the selection is being tracked (dashed line).
Some notes and suggestion about your implementation (it has quite a few issues):
As other members have noted, you may not call OnPaint() yourself. Especially those calls after Invalidate() make absolutely no sense. Instead, call UpdateWindow(), if you want an immediate update.
Imo it is NOT OK to perform calculations within OnPaint(), and I mean those points calculations (although in your case the calculation is rather trivial). OnPaint() should just display the data calculated in another part of your code.
Also, setting the m_cDiagram text and repainting from within OnPaint() is not OK either (may cause additional paint requests). Better move these into OnBnClickedButtongo().
You don't need to invalidate (and particularly erase) the whole client area to cause some controls to be repainted, instead invalidate only those controls. Remember, the sleep_for() function is blocking, and the WM_PAINT message won't be sent and processed while your loop is running.
Btw, consider a non-blocking approach, eg using a timer, as #Barmak Shemirani suggested. Alternatively, it may be possible to write a "non-blocing sleep()" by running the message-loop yourself (take parts of the code in CWinApp::Run() and modify it).
Since you have a dialog and created separate controls to display your data, using OnPaint() is not a good implementation, as it affects (paints) the whole client area. It is mostly useful for classes like CView or CScrollView (or custom-painting CWnds in general). You paint the graph on the dialog's surface, and have to perform calculations to get the coordinates in m_cDiagram (btw you can use GetWindowRect() and then ScreenToClient() instead) but it would be best to use an owner-drawn control (to paint/draw the graph on), and it's not really difficult, you just have to respond to paint requests (just as in OnPaint()), and the device context you get can paint on the control only, not on the dialog; coordinates are relative to the control's client area, starting from (0,0).
Hope this helps
CWnd::OnPaint is a response to WM_PAINT message and should not be called directly.
WM_PAINT calls CWnd::OnPaint, which calls CPaintDC dc(this), which in turns calls BeginPaint/EndPaint APIs. This sequence of message+response should be left as is.
Therefore CPaintDC dc(this) must appear once - and only once - inside OnPaint, and not anywhere else. Override OnPaint as follows:
void CMyDialog::OnPaint()
{
CDialogEx::OnPaint(); //this will call CPaintDC dc(this);
//optional:
CClientDC dc(this); //CClientDC can be used anywhere in a valid window
//use dc for drawing
}
//or
void CMyDialog::OnPaint()
{
CPaintDC dc(this);
//use dc for drawing
}
You also don't need the outdated if (IsIconic()) {...} condition.
To force the window to repaint itself, call Invalidate() (same thing as InvalidateRect(NULL, TRUE))
InvalidateRect(NULL, TRUE) is a request to repaint the window. The system will look at this request, and will send WM_PAINT message to that window when there is a chance. Therefore a call to InvalidateRect may not process the way you expect it to work in a sequential program. For example, a second consecutive call to InvalidateRect will not have any effect. Window was already marked to be updated.
for(int i(9); i >= 0; --i)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
m_fDiagramData.push_back((float)rand() / RAND_MAX);
InvalidateRect(NULL, TRUE);
OnPaint();
}
OnPaint() should be removed from above code. Still, animation is not possible in a single thread (at least not in this manner). The program is busy going through the loop, it cannot deal with WM_PAINT and other messages.
So you need an additional thread, or simply use SetTimer, and respond to ON_WM_TIMER()/OnTimer for animation. Example:
int counter = 0;
BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
ON_WM_PAINT()
ON_WM_TIMER()
...
END_MESSAGE_MAP()
void CMyDialog::OnPaint()
{
CPaintDC dc(this);
CString s;
s.Format(L"%02d", counter);
dc.TextOut(0, 0, s);
}
void CMyDialog::animate()
{
counter = 0;
SetTimer(1, 1000, NULL);
}
void CMyDialog::OnTimer(UINT_PTR n)
{
if(n == 1)
{
Invalidate(); //force repaint
counter++;
if(counter == 10)
KillTimer(1);
}
}

Qt - Adding a drawing to a Layout

I'm trying to make an application where the user can input some drawings (gestures) that will then be saved and displayed in a gallery on the top of the screen:
When the user presses "Validate", the drawing is supposed to be displayed on the scroll area on the top. However, for some reason, my code is not working the way I intended it to. It saves the drawing with no problem, but when I tell it to add it to the top, nothing happens.
Code here:
void MainWindow::galleryUpdate()
{
for (int i = 0; i < gestureTemplates.size(); i++)
{
QPolygonF scaledGesture = gestureTemplates[i].scaleToSquare(gestureTemplates[i]);
StrokeDrawer * strD = new StrokeDrawer();
QPalette Pal(palette());
Pal.setColor(QPalette::Background, Qt::white);
strD->setMinimumSize(50, 50);
strD->setAutoFillBackground(true);
strD->setPalette(Pal);
galleryList.append(strD);
topZone->addWidget(strD);
strD->setStroke(scaledGesture);
}
}
gestureTemplates is a vector of GestureTemplate (a custom class inheriting from QPolygonF) containing all the drawings. The first line inside the for simply scales the drawing to fit in a square, and returns a QPolygonF.
StrokeDrawer is the class used to display the drawing (code below). I then try to fill it with a white background, save it to galleryList which is a list of StrokeDrawer for each drawing, and then add it to the top, by using topZone->addWidget(strD), where topZone is a HBoxLayout.
I also use the setStroke method to set the drawing to the StrokeDrawer (this method also calls the update() function in the class, which calls its paintEvent, which should take care of actually drawing the QPolygonF).
Initially, I tried to do addWidget by directly using the QPolygonF but that didn't work. That's why I'm using this StrokeDrawer class (which just displays the drawing, it doesn't even allow making changes to it).
By debugging the code on QtCreator, everything works fine until the addWidget line, where nothing happens. I mean, even if the drawing is not being correctly displayed, it should at least show a small, white, 50x50 square, or am I missing something here?
Some code for StrokeDrawer:
void StrokeDrawer::setStroke(QPolygonF g)
{
gesture = g;
update();
}
void StrokeDrawer::paintEvent(QPaintEvent* e)
{
QWidget::paintEvent(e);
QPainter pait(this);
if (!gesture.empty())
pait.drawPolyline(gesture);
}

How to prevent mouseMoveEvent on QCursor::setPos() using Qt?

I am currently developing on an image viewer application. In this application I have a so called "pan-zoom" feature. This means that, when holding a certain mouse button, the user can zoom the image by panning forth and back.
It works fine, but as the feature is used, the mouse (naturally) moves up and down on the screen and will at some point reach the screen borders, which will make it stop. Instead I would like a behaviour where the mouse remains stationary and only the image magnification changes.
I tried to achieve this by invoking QCursor::setPos inside the QWidget::mouseMoveEvent and reset the mouse to the initial position after I have processed the move. It works so far as that the mouse is staying nearly stationary (it's wiggling forth and back). However, this will cause the mouse move event to be called again effectively annulling the adjustment I just made. This will result in a "wiggling" effect. Every adjustment will immediately be reversed.
Here is a code snipped, so you get an idea of what I am doing:
void ImageView::mouseMoveEvent(QMouseEvent *e) {
//some code
if (_panZooming) {
//some code here
//doesn't work as expected because it invokes this event again
QCursor::setPos(mapToGlobal(_initialMousePosition.toPoint()));
}
}
Is there a way to prevent the mouse move event to happen when using QCursor::setPos?
Assuming you're not calling the base class mouseMoveEvent, you should accept the event to mark it as being handled. By default, they're accepted when you re-implement the event, but it's clearer to be explicit. Call e->accept( ).
It's also recommended that if you handle any of the mouse events, you should handle all, with the possible exception of mouse double click.
Here's an example of keeping the mouse still, though on OS X there's an occasional flicker which appears to be due to how Qt is handling the events
class MyWidget : public QWidget
{
void mousePressEvent(QMouseEvent* e)
{
m_pos = e->globalPos();
m_lastPos = m_pos;
QWidget::mousePressEvent(e);
}
void mouseMoveEvent(QMouseEvent* e)
{
// Calculate relative zoom factor
// scaled down ( / 10 ) for image zooming
m_zoomFactor += ((float)e->globalPos().y() - m_lastPos.y()) / 10;
QCursor::setPos(m_pos);
m_lastPos = m_pos;
e->accept();
qDebug() << m_zoomFactor << endl;
}
void mouseReleaseEvent(QMouseEvent* e)
{
QWidget::mouseReleaseEvent(e);
}
private:
QPoint m_pos;
QPoint m_lastPos;
float m_zoomFactor = 0; // C++ 11 initialisation
};
If you're not bothered at keeping the mouse stationary, take out the QCursor::setPos call and this will still receive move events when the cursor is outside the widget, whilst the mouse button is held down.
However, it may be a better user experience hiding the cursor when zooming.
I would have a flag to disable the event with will be false by default.
inside the event check if flag is false, then perform the zoom operation, set flag to true and reset cursor.
then the event will be called again and the flag will be true, so you set flag to false and you will be ready to handle the next event.
You just have to make sure you dont have two or more calls to the mouse event firing from the actual mouse before receiving the event from the setCursor call.
Don't use event->pos() in mouse events, use QCursor::pos() intead and check if it changed. Like this:
void MyWidget::mousePressEvent(QMouseEvent *)
{
mPrevPos=QCursor::pos();
mMoving=false;
}
void MyWidget::mouseMoveEvent(QMouseEvent *)
{
auto cursorPos=QCursor::pos();
if(mPressedPos==cursorPos){
return;
}
if(!mMoving
&& (cursorPos-mPrevPos).manhattanLength()>QApplication::startDragDistance()){
mMoving=true;
}
if(mMoving){
auto diff=cursorPos-mPrevPos;
// move something using diff
QCursor::setPos(mPrevPos);
}
}
void MyWidget::mouseReleaseEvent(QMouseEvent *)
{
mMoving=false;
}
void MyWidget::leaveEvent(QEvent *)
{
mMoving=false;
}

Need help in optimizing a drawing code ...

I needed some help in trying to optimize this code portion ... Basically here's the thing .. I'm making this 'calligraphy pen' which gives the calligraphy effect by simply drawing a lot of adjacent slanted lines ... The problem is this: When I update the draw region using update() after every single draw of a slanted line, the output is correct, in the sense that updates are done in a timely manner, so that everything 'drawn' using the pen is immediately 'seen' the drawing.. however, because a lot (100s of them) of updates are done, the program slows down a little when run on the N900 ...
When I try to do a little optimization by running update after drawing all the slanted lines (so that all lines are updated onto the drawing board through a single update() ), the output is ... odd .... That is, immediately after drawing the lines, they lines seem broken (they have vacant patches where the drawing should have happened as well) ... however, if I trigger a redrawing of the form window (say, by changing the size of the form), the broken patches are immediately fixed !! When I run this program on my N900, it gets the initial broken output and stays like that, since I don't know how to enforce a redraw in this case ...
Here is the first 'optimized' code and output (partially correct/incorrect)
void Canvas::drawLineTo(const QPoint &endPoint)
{
QPainter painter(&image);
painter.setPen(QPen(Qt::black,1,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
int fx=0,fy=0,k=0;
qPoints.clear();
connectingPointsCalculator2(qPoints,lastPoint.x(),lastPoint.y(),endPoint.x(),endPoint.y());
int i=0;
int x,y;
for(i=0;i<qPoints.size();i++)
{
x=qPoints.at(i).x();
y=qPoints.at(i).y();
painter.setPen(Qt::black);
painter.drawLine(x-5,y-5,x+5,y+5); **// Drawing slanted lines**
}
**//Updating only once after many draws:**
update (QRect(QPoint(lastPoint.x()-5,lastPoint.y()-5), QPoint(endPoint.x()+5,endPoint.y()+5)).normalized());
modified = true;
lastPoint = endPoint;
}
Image right after scribbling on screen:
http://img823.imageshack.us/img823/8755/59943912.png
After re-adjusting the window size, all the broken links above are fixed like they should be ..
Here is the second un-optimized code (its output is correct right after drawing, just like in the second picture above):
void Canvas::drawLineTo(const QPoint &endPoint)
{
QPainter painter(&image);
painter.setPen(QPen(Qt::black,1,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
int fx=0,fy=0,k=0;
qPoints.clear();
connectingPointsCalculator2(qPoints,lastPoint.x(),lastPoint.y(),endPoint.x(),endPoint.y());
int i=0;
int x,y;
for(i=0;i<qPoints.size();i++)
{
x=qPoints.at(i).x();
y=qPoints.at(i).y();
painter.setPen(Qt::black);
painter.drawLine(x-5,y-5,x+5,y+5); **// Drawing slanted lines**
**//Updating repeatedly during the for loop:**
update(QRect(QPoint(x-5,y-5), QPoint(x+5,y+5)).normalized());//.adjusted(-rad,-rad,rad,rad));
}
modified = true;
int rad = (myPenWidth / 2) + 2;
lastPoint = endPoint;
}
Can anyone see what the issue might be ?
Sorry if I misunderstood, but have you tried to use the "double buffer" approach? Instead of drawing directly on the screen, you "draw" your points and lines to a memory buffer. After that, you just copy the buffer to the screen. This is faster and avoids flickering.
As I understand you should find min and max of x and y processed in your for-loop and use them in update(QRect(QPoint(minX-5, minY-5), QPoint(maxX+5, maxY+5)).normalized());
I'm not sure exactly what your issue is with the broken lines, but I can offer you this advice: keep your pen around. Instead of this:
for(i=0;i<qPoints.size();i++)
{
// ...
painter.setPen(Qt::black);
painter.drawLine(x-5,y-5,x+5,y+5); **// Drawing slanted lines**
// ...
}
do this:
QPen black_pen(Qt::black);
for(i=0;i<qPoints.size();i++)
{
// ...
painter.setPen(black_pen);
painter.drawLine(x-5,y-5,x+5,y+5); **// Drawing slanted lines**
// ...
}
Even more, if you are repeatedly calling your drawLineTo function with the same pen every time, store the pen in your class and keep it around. At my company, we've found that to vastly reduce drawing times where we can take advantage of it. (One instance on a large image cut drawing times in half.)
One other note: I'm not sure what type the image you are painting is, but I'm assuming it is a QImage. When you are done drawing, if you will be using the unmodified image repeatedly, you might convert it once to a QPixmap. The QPixmap class is stored in a way that is supposed to be ready for blitting directly to the screen (but it a lot slower to modify in many cases, because of that).

How to programmatically move a window slowly, as if the user were doing it?

I am aware of the MoveWindow() and SetWindowPos() functions. I know how to use them correctly. However, what I am trying to accomplish is move a window slowly and smoothly as if a user is dragging it.
I have yet to get this to work correctly. What I tried was getting the current coordinates with GetWindowRect() and then using the setwindow and movewindow functions, incrementing Right by 10 pixels each call.
Any ideas?
Here is what I had beside all my definitions.
while(1)
{
GetWindowRect(notepad,&window);
Sleep(1000);
SetWindowPos(
notepad,
HWND_TOPMOST,
window.top - 10,
window.right,
400,
400,
TRUE
);
}
If you want smooth animation, you'll need to make it time-based, and allow Windows to process messages in between movements. Set a timer, and respond to WM_TIMER notifications by moving the window a distance based on the elapsed time since your animation started. For natural-looking movement, don't use a linear function for determining the distance - instead, try something like Robert Harvey's suggested function.
Pseudocode:
//
// animate as a function of time - could use something else, but time is nice.
lengthInMS = 10*1000; // ten second animation length
StartAnimation(desiredPos)
{
originalPos = GetWindowPos();
startTime = GetTickCount();
// omitted: hwnd, ID - you'll call SetTimer differently
// based on whether or not you have a window of your own
timerID = SetTimer(30, callback);
}
callback()
{
elapsed = GetTickCount()-startTime;
if ( elapsed >= lengthInMS )
{
// done - move to destination and stop animation timer.
MoveWindow(desiredPos);
KillTimer(timerID);
}
// convert elapsed time into a value between 0 and 1
pos = elapsed / lengthInMS;
// use Harvey's function to provide smooth movement between original
// and desired position
newPos.x = originalPos.x*(1-SmoothMoveELX(pos))
+ desiredPos.x*SmoothMoveELX(pos);
newPos.y = originalPos.y*(1-SmoothMoveELX(pos))
+ desiredPos.y*SmoothMoveELX(pos);
MoveWindow(newPos);
}
I found this code which should do what you want. It's in c#, but you should be able to adapt it:
increment a variable between 0 and 1 (lets call it "inc" and make it global) using small increments (.03?) and use the function below to give a smooth motion.
Math goes like this:
currentx=x1*(1-smoothmmoveELX(inc)) + x2*smoothmmoveELX(inc)
currenty=y1*(1-smoothmmoveELX(inc)) + y2*smoothmmoveELX(inc)
Code:
public double SmoothMoveELX(double x)
{
double PI = Atn(1) * 4;
return (Cos((1 - x) * PI) + 1) / 2;
}
http://www.vbforums.com/showthread.php?t=568889
A naturally-moving window would accelerate as it started moving, and decelerate as it stopped. The speed vs. time graph would look like a bell curve, or maybe the top of a triangle wave. The triangle wave would be easier to implement.
As you move the box, you need to steadily increase the number of pixels you are moving the box each time through the loop, until you reach the halfway point between point a and point b, at which you will steadily decrease the number of pixels you are moving the box by. There is no special math involved; it is just addition and subtraction.
If you are bored enough, you can do loopback VNC to drag the mouse yourself.
Now, as for why you would want to I don't know.