I'm learning C++ and SFML right now, trying to create a chess program in which I can drag and drop the pieces around the board. I drag the pieces by checking if the left mouse button is down and if the mouse is over a piece. If these are both true, I change the position of the piece to that of the mouse.
The only problem is when I drag the pieces really quickly, thus having my mouse down but not hovering over the piece.
I want to fix this using something like:
sf::Sprite pieceSelected;
sf::Sprite Pawn;
bool selected;
...
if (LeftButtonDown && isMouseOver(Pawn,Input)) {
pieceSelected=&Pawn;
selected = true;
}
if (LeftButtonDown && selected)
pieceSelected.SetPosition(MouseX - (XSizeSprite / 2), MouseY - (YSizeSprite / 2));
else
selected=false;
App.Draw(Pawn);
I want 'pieceSelected' to be referencing 'Pawn' so that when I'm moving 'pieceSelected' I'm actually moving 'Pawn' at the same time.
EDIT
I fixed this by changing
sf:Sprite pieceSelected;
to
sf::Sprite * pieceSelected;
and
pieceSelected.SetPosition
to
pieceSelected->SetPosition
Right, from the comments I spotted the problem. Your drag-and-drop code repeatedly picks up and drops the pawn. That's indeed not the correct solution. Instead, you should only drop the piece on a LeftMouseUp.
What you want is a DragOperation class. You create it when you detect the begin of a drag operation (mouse down over a pawn). The DragOperation class has a sf::Sprite & pieceSelected, set of course in its constructor. You should also store both the mouse and pawn coordinates where the drag operation started.
While dragging, the responsibility of drawing the selected piece should be moved to the DragOperation class. This allows you to smoothly drag the pawn, in pixel increments, instead of drawing it only in the middle of a square.
When the mouse button is released, check the result and then delete your DragOperation object.
Related
I'm trying to implement a way to click and drag the screen in SFML. The idea being that when the user clicks down on their mouse, an sf::View gets changed by how much the user moves their mouse until they release it.
I tried to use the sf::Event::MouseMoveEvent struct under the assumption it would give the mouse movement and not the position. When I used it in code, however, it gets the position.
I could try and keep track of the previous mouse position and subtract it out to get the change, but I would expect that there would be a struct or function that would give me the delta position. It has this functionality for the scroll wheel, so I'd hope it does for the mouse.
I have a strange issue that I have been unable to determine the cause. Basically, I created a 2D view with pan and zoom functionality and a scene with items that can moved with grid snapping. To move an item in the scene I extended Scene::mousePressEvent to get a pointer to the item and Scene::mouseMoveEvent to keep the item tracked on the cursor. To drop the item, I used Scene::mousePressEvent again. To pan, I extended View::mousePressEvent, View::mouseReleaseEvent, and View::mouseMoveEvent and to zoom I extended View::wheelEvent.
Now for the symptoms:
I start the application with an item in the Scene. If I click and hold, then move the mouse, the item moves as intended. As soon as I release the mouse button, the item stops moving. I can click to drop and the item is placed according to the drop code in Scene::mousePressEvent. Try again and still the item only moves when the mouse button is pressed.
Then comes the strange part: If I use the mouse wheel to zoom the View, everything performs as expected after that event. The mouse is clicked to select an item, it moves as I move the mouse and drops when I click again.
So the obvious solution:
wheelEvent(new QWheelEvent(QPointF(0,0),0,Qt::NoButton,Qt::NoModifier));
called at the creation of the View and everything works fine. It calls the extended View::wheelEvent with no change to the view and before the scene is even created, but afterwards the programs behaves as expected.
So I'm here to see if any of the excellent Qt experts out there can explain this strange behavior. Any comments or direction are appreciated.
In case it helps, here is the View::wheelEvent override code. tform is a QTransform with which I maintain zoom. Also, I've tried with and without the call to the base method but there is no change in behavior.
void SchematicView::wheelEvent(QWheelEvent* event)
{
// Scale the view / do the zoom
double scaleFactor = 1.1;
if(event->delta() > 0 && tform.m11() < max_zoom) {
tform.scale(scaleFactor,scaleFactor);
} else if (event->delta() < 0 && tform.m11() > min_zoom){
tform.scale(1.0/scaleFactor,1.0/scaleFactor);
}
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setTransform(tform);
QGraphicsView::wheelEvent(event);
}
Without a SSCCE to look at and test with, it's hard to say for sure, but what you're describing sounds a lot like your mouseMoveEvent() callback is only getting called when the mouse button is being held down during the move. That, in turn, sounds a lot like the expected behavior for mouseMoveEvent(), as documented in QWidget::mouseMoveEvent():
If mouse tracking is switched off, mouse move events only occur if a
mouse button is pressed while the mouse is being moved. If mouse
tracking is switched on, mouse move events occur even if no mouse
button is pressed.
If that is indeed the problem, then a call to setMouseTracking(true) may get you the behavior you are looking for.
On a broader level, note that there are easier ways of obtaining the behavior you are trying to implement -- for example, to allow the user to drag and drop items in a QGraphicsScene, all you really have to do is call setFlags(QGraphicsItem::ItemIsMovable) on any QGraphicsItems that you want the user to be able to drag around. No hand-coding of event handlers is necessary unless you are trying to obtain some non-standard behaviors.
I'm programming my first 2D game in Qt.
I have QWidged where I draw my game (isometric view). When mouse enters border of widget it moves map view (like in every strategy game...).
And here is my trouble... I'm tracking mouse position with mouseMoveEvent but it fires only when mouse moves (only when position changes). So map moves only when I move mouse at borders. If mouse stand still, map does not move (mouseMoveEvent is not triggered). And I have no idea how to solve this. It's annoying when you try to play it.
This is my first post here.. and I hope that I explained my problem clearly :)
Edit (little more clarify):
Imagine this: you want to move map. So you move mouse to the edge of screen (QWidget) but at the moment when you stop mouse, map stops moving too. But mouse is still at edge of screen. What I want to do is that map will still move after mouse stops at edge.
You can create QPropertyAnimation for coordinates and start/stop it when mouse moves to/from widget's border.
Or you can remember current state ("changing x by -1 every 100ms, changing y by 0") and call some slot that does the real moving with QTimer.
I am implementing a function (Using Qt) that is supposed to move a widget to the cursor position as part of a drag and drop functionality.
I have three events that get triggered, mouse down, mouse move, and mouse up. When the mouse moves and is down, a signal is sent to the widget to move itself to the cursor; however, I have encountered some strange behavior.
This simple code:
void Block::moveToCursor()
{
block->move(block->mapFromGlobal(QCursor::pos()));
qDebug() << block->mapFromGlobal(QCursor::pos());
}
where "block" is a QLabel that is a member of Block and is a child of the window's central widget.
It produces this result:
As it can be seen in the debug output, the coordinates are flip flopping (or flickering) every time there is a pixel move. The first coordinated are correct but the second set of coordinates seem to be relative to the top right corner of the window.
I have tried all the mapping functions:
block->move(block->mapFromParent(QCursor::pos()));
-Produces a similar result with the second set of coordinates relative to the center of the window.
block->move(block->mapFrom(this->block, QCursor::pos()));
-This produces an even stranger result. The block does not flicker and moves correctly with respect to the mouse, but the initial position of the block seems to be off by the distance from the top right corner of the computer screen. It also only shows one point when printed out in debug, yet it is moving on the screen. Every time you see Continue Drag, the mouse has moved at least one pixel.
Can someone explain this strange behavior to me and show me the correct way of moving the widget to the cursor at the exact position from where it was originally clicked?
To get the coordinate in relation to the parent (like wanted from move()-Method), you need to use the mapFromGlobal on the parent like this:
block->move(block->parentWidget()->mapFromGlobal(QCursor::pos()));
Just give it a try. The reason for this is, lets consider what happens when you are at position 1,1 inside the child. But the child is for example at position 123,123 from its parent top-left. You would now move it to 1,1, causing it to jump 122 pixels each.
https://stackoverflow.com/questions/9466359/graphics-editor-in-c
I've developed a simple graphics editor in c++.It requires me to drag the mouse to draw a shape .After drawing the shape I want to fill it by picking a color but since dragging the mouse amounts to a large number of clicks because of which the entire screen gets filled with a default color even before i've drawn the shape. delay() doesn't work either.
the mouse click event in turbo c++ has two part. one where you press the button and two when you release the button. you need to drag so you should use the clrscr() function in the loop which goes on iterating until the mouse button is pressed down along with the code for the shape you want to draw. that way your screen keeps getting updated when you are dragging the mouse. and the loop ends when you release the button.
for filling the shape using the flood fill function should suffice
Perhaps one of the following links is what you're looking for:
http://www.codeproject.com/Articles/11313/Mouse-Programming-in-C-C
http://www.cprogrammingreference.com/Tutorials/Advance_Tutorials/mouseprogramming.php
http://www.brackeen.com/vga/mouse.html