Force update drawForeground on QGraphicsScene - c++

I want to show a little image on my mouse position.
So i did that:
void AreaScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event){
MapData::pEnd.setX(event->scenePos().x());
MapData::pEnd.setY(event->scenePos().y());
this->update(0, 0, this->width(), this->height());
}
The pEnd is my point.
On the drawForeground i did that:
void AreaScene::drawForeground(QPainter *painter, const QRectF &rect){
qDebug() << "called";
if(MapData::tileIndex!=-1&&MapData::pEnd.x()!=-1){
painter->drawPixmap(MapData::pEnd.x(),MapData::pEnd.y(), *MapData::tileImage, (((int)(MapData::tileIndex%(MapData::tileImage->width()/MapData::tileSize.x())))*MapData::tileSize.y()),
(((int)(MapData::tileIndex/(MapData::tileImage->width()/MapData::tileSize.x())))*MapData::tileSize.x()),
MapData::tileSize.x(), MapData::tileSize.y());
}
}
Note:
The tile index is the position of the subrectangle on the tileImage (QPixelMap)
So i get the points, the image and the subrectange inside it.
It works if i keep pressing the right or the left mouse buttons it updates, but i want to update it when i move the mouse, i know the drawForeground is not even called at all.
Is there a way to call it, force to update so i can show the little tile on the screen?
The another option (i think) is change the mouse icon to the tile image, but i did a little research and didn't find a way to do that.
Thanks ppl

Call setMouseTracking(true); on the QGraphicsView that is displaying the scene. That will tell the view to generate mouse move events whenever the mouse is hovered over the view. Otherwise, the view will only generate mouse move events when you click and drag while holding down a mouse button.

Related

How to know if the mouse hovers over a widget in QT?

I am trying to implement in my program, that if the mouse hovers over my QChartView widget, that I get back the coordinates of the cursor.
I already tried, by installing an event filter on the widget
ui->chartView->setMouseTracking(true);
ui->chartView->installEventFilter(this);
and then writing the method for a mouse event
void MainWindow::mouseMoveEvent(QMouseEvent* event) {
qDebug() << event->pos();
}
but, i only get output when I click on the Mainwindow and hold the mousebutton which I clicked. When I click on the widget chartView I dont get any output.
I need to get output, when the mouse is hovering over the chartview
You don't need an event filter. You need to reimplement the methods QWidget::enterEvent() and QWidget::leaveEvent().
enterEvent() is called when the mouse enters the widget and leaveEvent() when it leaves it again.

Accessing the the coordinates in a QPushbutton clicked slot

I have a QPushButton with an image that has two areas that I want to handle differently when clicked. Due to the positioning on the image, I cannot really use separate buttons for the two images.
What I'd like to do is, in the slot where I am handling the click, have it check the coordinates of the click to determine which area was clicked.
Is there a way to access this?
This is what first comes to mind. It should work, although there may be a simpler way:
Create your own class that derives from QPushButton.
Override the necessary mouse events (mousePressEvent and mouseReleaseEvent) and, before calling the base class implementation, set a property in your object using setProperty with the position of the mouse click. (The position is available from the event parameter.)
In the slot handling the event, use sender() to get the button, and read the property using property().
If you don't need to treat your object as the base class (QPushButton*) you could just create a new signal that includes the mouse event and attach that to your slot. Then you wouldn't need the property at all.
You can get the current mouse position using QCursor::pos() which returns the position of the cursor (hot spot) in global screen coordinates.
Now screen coordinates are not easy to use, and probably not what you want. Luckily there is a way to transform screen coordinates to coordinates relative to a widget.
QPoint _Position = _Button->mapFromGlobal(QCursor::pos());
This should tell you where on the button the mouse was when the user clicked. And you can take it from there.
Building on #Liz's simple mechanism, here's what I did; this is in a slot method that is called on pressed() but generalizes to other situations. Note that using pushButton->geometry() gives you coordinates that are already in global space so you don't need to mapFromGlobal.
void MainWindow::handlePlanButtonPress()
{
int clickX = QCursor::pos().x();
int middle = m_buttonPlan->geometry().center().x();
if ( clickX < middle ) {
// left half of button was pressed
m_buttonPlan->setStyleSheet(sStyleLargeBlueLeft);
} else {
// right half of button was pressed
m_buttonPlan->setStyleSheet(sStyleLargeBlueRight);
}
}

QGraphicsView not repainting on scroll event

QT 4.7
I have a QGraphicsView / QGraphicsScene. The scene has a custom QGraphicsItem the whole scene is not displayed at one time, so it has a viewport.
I'm overriding the paint() method of my QGraphicsItem as follows:
void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
painter->setClipRect(option->exposedRect);
painter->save();
// Default identity matrix
QTransform transform;
// Apply some transform later
// The next line breaks stuff
painter->setTransform(transform);
// m_image is just a preloaded pixmap (i.e. watermark on all of these items).
painter->drawImage(QPoint(0,0), this->m_image);
painter->restore();
// Snip, do more drawing...
}
If I ever try to setTransform on the QPainter (i.e. if I'm trying to rotate the item), the view stops repainting the scene as a response to the horizontal or vertical scrollbars used to pan. The view also stops resizing the scene when I zoom in or zoom out.
The view will refresh if I resize the window or drag the window offscreen and then back onscreen. I've been looking over the QPainter Documentation as well as the examples and I can't quite figure out what I'm doing wrong. I'm assuming it's something to do with the coordinate system.
A guess:
The QPainter that comes to your paint method already has a transform on it that takes into account the viewport attributes (scale, rotation, etc.). When you call setTransform within your paint method you are blowing all that away. You probably want to perform a matrix operation on the existing transform rather than creating a new one.
Since you are calling setClipRect on your painter but then trying to paint under a completely different transform, you are painting outside your clip rect and nothing is happening.
It works when you resize or drag the window off screen because that forces a "redraw everything," so your clip rect includes your painting area in your alternate transform. Although I'm surprised it would appear in the correct location.

Dragging object around a QWidget in Qt

I am trying to make a custom widget in Qt Creator that supports dragging objects around. At its simplest form, the widget has a QRect (or any other shape), on which I can click and then drag it around the widget. Once I release the mouse button, the QRect should stop being dragged.
In my QWidget class, I have this method
void ImageArea::mouseMoveEvent(QMouseEvent *event)
{
QPoint mousePos = event->pos();
qDebug() << mousePos.x();
qDebug() << mousePos.y();
qDebug() << "---------";
}
that can get the coordinates of the mouse as the pointer is moved around the screen. I have tried updating member variables for x and y, and then painting the QRect via the paintEvent method, but this doesn't work.
Does anyone have any suggestions?
To get mouse move events, you must set the QWidget::mouseTracking property to true:
ImageArea::ImageArea( QWidget* p ) : QWidget( parent ) {
...
setMouseTracking( true );
}
Implement paintEvent(QPaintEvent *) to draw the object(s) at the positions indicated by the current value(s) of their corresponding member variables.
After you've changed the values of one or more member variables (in mouseMoveEvent or wherever), call this->update(). That will tell Qt that it needs to call your paintEvent method again in the near future.
That should be all you need to do.
Be sure to use the moveTo method to move the rectangle.
Setting the x,y position directly may affect the size of the rectangle.
I don't see what you aren't doing, based on your question.
Are you sure that the rectangles are in new positions when you paint them?
Maybe you are missing the update step Jeremy Friesner told to implement.
It seems that you are missing mouse button tracking.
The easy way might be to get the mouse button states from QApplication::mouseButtons(). Although it might be slightly less efficient.

QT mouse event handling problem

Greetings all,
As seen in the picture
I have an extended QWidget object (which draws the cell images and some countour data) inside a QScrollBar.
User can zoom in/out the Image (QWidget size is changed according to the zoomed size of the QImage ) using mouse wheel.
I process the events (mouseMoveEvent(),wheelEvent()..etc) by implementing the listener methods in QWidget.
My problem is ,I can only perform zooming (and other events) when the mouse pointer is over the QWidget.
If the mouse point is over the QScrollBar (the gray area in the image) ,those events are consumed by the QScroolBar.
Any tips,
[Edit] Sorry I was refering to QScrollArea , not QScrollBar.
thanks,
umanga
I'm uncertain if you want the scroll wheel to only ever be used for zooming the image or if you want the scroll wheel to control zooming when the image is smaller than the scroll area viewport and then use the scroll wheel to do scrolling when the image is larger than the scroll area viewport. In either case, you should be able to customize how the wheel is handled with the following:
Since I've not actually tried this one, I'm not sure if it will work. The hope is that if you install an event filter and set ignore on the event, the event will still be propagated back to your image widget. This will allow you to leave your current mouse handling in the image widget intact.
bool YourImageWidget::eventFilter(QObject *obj, QEvent *event)
{
if((obj == scrollAreaPointer) && (event->type() == QEvent::Wheel))
{
if(!scrollAreaShouldHandleWheel)
{
event->ignore();
}
}
return false; // always pass the event back to the scroll area
}
The scrollAreaShouldHandleWheel flag is a boolean you would set from your image widget based on whether or not you want the scroll area to handle the wheel events.
Somewhere in your code you would install your image widget as an event filter for the scrollarea.
scrollArea->installEventFilter(imageWidget);
If this doesn't work, you can always use this filter to make sure your widget gets the event and handle it directly and then return true so that the scroll area won't be able to receive the event.
I recommend you use QGraphicsScene and QGraphicsView. The graphics framework already provides a lot of useful features (including viewport transformation). And the QGraphicsView is a scroll area.
have you done grabMouse() for Qwidget i.e for the one which you display image?