I have created a Qwidget with a QRect. Now I would like to move this Rect with my keyboard. Which does not work. When trying with a mousePressEvent instead of the keyPressEvent, everything is working fine though. There are no Focuses yet set, which probably is the problem here. But it's the first time I have to work with those and I just can't figure out what to do and how to use them, even after searching online for the last hours.
I tried putting setFocusPolicy(Qt::StrongFocus) in my widgets constructor amongst other things, but nothing has worked so far. Maybe I'm just blind to an obvious solution, but please help? Thanks alot already
my paint event:
void zeichenFeld::paintEvent(QPaintEvent *event)
{
QPainter painter;
painter.begin (this);
//Avatar:
QRect rectAv=QRect(xAv, yAv, 20,20);
painter.fillRect(rectAv, Qt::BrushStyle::SolidPattern);
painter.fillRect(rectAv, colorAv);
painter.drawRect(rectAv);
painter.end();
}
void zeichenFeld::keyPressEvent(QKeyEvent *event)
{
if(event->key()==Qt::Key_A){
xAv-=10;
}
if(event->key()==Qt::Key_D){
xAv+=10;
}
update();
}
void zeichenFeld::mousePressEvent(QMouseEvent *event){
if(event->button()==Qt::LeftButton)
{
xAv-=25;
}
if(event->button()==Qt::RightButton)
{
xAv+=25;
}
update();
}
header:
protected:
void paintEvent(QPaintEvent *event);
void keyPressEvent(QKeyEvent *event);
void mousePressEvent(QMouseEvent *event);
Edit: i simply added the setFocusPolicy(Qt::StrongFocus); to the wrong contructor. Working now
a QRect is not a visual class, so if you used the PaintEvent to draw a rectangle, then you need to come up with your special way to handle that in the mouse press event.
something like:
YourClass.h
protected:
void mousePressEvent(QMouseEvent *ev) override;
void mouseMoveEvent(QMouseEvent *ev) override;
void mouseReleaseEvent(QMouseEvent *ev) override;
private:
QRect _myRect;
YourClass.cpp
void YourClass::mousePressEvent(QMouseEvent *ev) {
if (_myRect.contains(ev->localPos())){
_isRectSelected = true;
}
}
void YourClass::mouseMoveEvent(QMouseEvent *ev) {
if (_isRectSelected) {
_myRect->setX(ev->localPos().x());
_myRect->setY(ev->localPos().y());
}
}
void YourClass::mouseReleaseEvent(QMouseEvent *ev) {
if (_isRectSelected) {
_isRectSelected = false;
}
}
but I wouldn't reccomend that. Try to use QGraphicsView with QGraphicsRectItem as it's a visual class. it knows how to paint itself and it also has mouse handling.
Or even better, Qml.
Related
I implement drag&drop feature to my project. I can drag&drop.It works fine but override method not getting called.
Am I missing something ?
protected:
void mousePressEvent(QMouseEvent *event)override;
void mouseMoveEvent(QMouseEvent *event)override;
void dragEnterEvent(QDragEnterEvent *event)override;
void dragMoveEvent(QDragMoveEvent *event)override;
void dropEvent(QDropEvent *event)override;
void InformationMusteriDialog::dropEvent(QDropEvent *event) {
QMessageBox::information(this,"dropEvent","dropEvent");
}
void InformationMusteriDialog::mousePressEvent(QMouseEvent *event)
{
QMessageBox::information(this,"mousePressEvent","mousePressEvent");
}
void InformationMusteriDialog::mouseMoveEvent(QMouseEvent *event)
{
QMessageBox::information(this,"mouseMoveEvent","mouseMoveEvent");
}
void InformationMusteriDialog::dragEnterEvent(QDragEnterEvent *event)
{
QMessageBox::information(this,"dragEnterEvent","dragEnterEvent");
}
void InformationMusteriDialog::dragMoveEvent(QDragMoveEvent *event)
{
QMessageBox::information(this,"dragMoveEvent","dragMoveEvent");
}
when i drag or drop nothing pops up.
(I'm reading these links contents for 2 days. Please dont say read the doc again)
https://doc.qt.io/qt-5/dnd.html
https://www.informit.com/articles/article.aspx?p=1405546
I read this but mine still not working
dropEvent() not getting called
I dont understand what`s going on: when i create QGraphicsView object directly and adding scene with a pixmap, all is ok, pixmap appears on the screen:
scene.addPixmap(pix);
QGraphicsView graphicsView;
graphicsView.setScene(&scene);
But when i try to inherit QGraphicsView class with purpose of reimplementing events, nothing happend and i got white screen without pixmap, but events like changing cursor is working:
scene.addPixmap(pix);
DrawArea graphicsView;
graphicsView.setScene(&scene);
.h file:
class DrawArea : public QGraphicsView
{
Q_OBJECT
public:
DrawArea(QWidget *parent = 0);
~DrawArea();
signals:
public slots:
void mousePressEvent(QMouseEvent * e);
void paintEvent(QPaintEvent *);
void enterEvent(QEvent *e);
private:
QPoint coord;
};
.cpp file:
DrawArea::DrawArea(QWidget *parent)
: QGraphicsView(parent){
}
DrawArea::~DrawArea(){
}
void DrawArea::mousePressEvent(QMouseEvent * event){
}
void DrawArea::paintEvent(QPaintEvent *event){
}
void DrawArea::enterEvent(QEvent *event){
viewport()->setCursor(Qt::CrossCursor);
}
Tell me if something missed, Thanks in advance.
You should process your events. Try this:
void DrawArea::mousePressEvent(QMouseEvent * event)
{
//some actions
QGraphicsView::mousePressEvent(event);
}
void DrawArea::paintEvent(QPaintEvent *event)
{
//some actions
QGraphicsView::paintEvent(event);
}
Also I think that you don't need paintEvent at all, do all needed things in the scene.
Ok, I've been able to get get Drag and Drop working on QGraphicsScene, but not QGraphicsView. My code looks something like this:
class GraphicsView : public QGraphicsView
{
public:
GraphicsView(QGraphicsScene *scene) : QGraphicsView(scene) {}
protected:
void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
event->setAccepted(true);
update();
}
void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
event->setAccepted(true);
update();
}
void dropEvent(QGraphicsSceneDragDropEvent *event)
{
//stuff that never runs...
update();
}
};
Although, this code works perfectly fine with QGraphicsScene inherited instead of QGraphicsView. I also ran the setAcceptDrops(true) function. What am I doing wrong?
I'm new to the cocos2d(-x) world.
I'd like to detect a touch to a sprite, and tutorials/examples seem to suggest using layer to detect touch and find the approapriate sprite with bounding box.
Is subclassing sprite to allow touch detection generally a bad idea?
Note: This answer might be outdated. I answered this at 2012.
It is not a bad idea. Here is how I do it:
header file:
#include "cocos2d.h"
using namespace cocos2d;
class TouchableSprite : public cocos2d::CCSprite, public CCTargetedTouchDelegate {
public:
virtual void onEnter();
virtual void onExit();
virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);
};
cpp file:
#include "TouchableSprite.h"
void TouchableSprite::onEnter(){
// before 2.0:
// CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true);
// since 2.0:
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
CCSprite::onEnter();
}
void TouchableSprite::onExit(){
// before 2.0:
// CCTouchDispatcher::sharedDispatcher()->removeDelegate(this);
// since 2.0:
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
CCSprite::onExit();
}
bool TouchableSprite::ccTouchBegan(CCTouch* touch, CCEvent* event){
//do whatever you want here
return true;
}
void TouchableSprite::ccTouchMoved(CCTouch* touch, CCEvent* event){
//do what you want
}
void TouchableSprite::ccTouchEnded(CCTouch* touch, CCEvent* event){
//do your job here
}
In cocos2d-x 3.0 alpha you can try this:
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = [&](Touch* touch, Event* event){
if (this->getBoundingBox().containsPoint(this->convertTouchToNodeSpace(touch))) {
return true;
}
return false;
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
it is better and much more clear to handle touches in one place. but i think, no one can bar you to do this
You do not need to subclass sprites to detect touch.
Here, Follow this LINK its a nice place to get started with Cocos2d
I'm trying to make a simple draggable item using the graphics framework. Here's the code for what I did so far:
Widget class:
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
};
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
DragScene *scene = new DragScene();
DragView *view = new DragView();
QHBoxLayout *layout = new QHBoxLayout();
DragItem *item = new DragItem();
view->setAcceptDrops(true);
scene->addItem(item);
view->setScene(scene);
layout->addWidget(view);
this->setLayout(layout);
}
Widget::~Widget()
{
}
DragView class:
class DragView : public QGraphicsView
{
public:
DragView(QWidget *parent = 0);
};
DragView::DragView(QWidget *parent) : QGraphicsView(parent)
{
setRenderHints(QPainter::Antialiasing);
}
DragScene class:
class DragScene : public QGraphicsScene
{
public:
DragScene(QObject* parent = 0);
protected:
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
};
DragScene::DragScene(QObject* parent) : QGraphicsScene(parent)
{
}
void DragScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event){
}
void DragScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event){
}
void DragScene::dragLeaveEvent(QGraphicsSceneDragDropEvent *event){
}
void DragScene::dropEvent(QGraphicsSceneDragDropEvent *event){
qDebug() << event->pos();
event->acceptProposedAction();
DragItem *item = new DragItem();
this->addItem(item);
// item->setPos(event->pos()); before badgerr's tip
item->setPos(event->scenePos());
}
DragItem class:
class DragItem : public QGraphicsItem
{
public:
DragItem(QGraphicsItem *parent = 0);
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
protected:
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};
DragItem::DragItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
setFlag(QGraphicsItem::ItemIsMovable);
}
QRectF DragItem::boundingRect() const{
const QPointF *p0 = new QPointF(-10,-10);
const QPointF *p1 = new QPointF(10,10);
return QRectF(*p0,*p1);
}
void DragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
if(painter == 0)
painter = new QPainter();
painter->drawEllipse(QPoint(0,0),10,10);
}
void DragItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event){
}
void DragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event){
}
void DragItem::mousePressEvent(QGraphicsSceneMouseEvent *event){
QMimeData* mime = new QMimeData();
QDrag* drag = new QDrag(event->widget());
drag->setMimeData(mime);
drag->exec();
}
void DragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event){
}
main.cpp instantiates a Widget and shows it. When I try to drag the circle, the app just creates another circle over the original one, regardless of where I release the drag. qDebug() in DragScene's dropEvent() shows QPointF(0,0) everytime the drag ends. I'm having a hard time trying to understand exactly what I have to do, which classes I should subclass, which methods needs to be overriden, to make this work. The documentation on this isn't very detailed. I'd like to know how to make this work, and if there's some other, more comprehensive resource to learn about the graphics view framework, besides the official documentation (which is excellent btw, but it would be great if there was a more detailed treatise on the subject).
EDIT:
Following badgerr's advice, I replaced item->pos() in DragScene::dropEvent() with item->scenePos(), now the drop event creates a new circle in the drop site, which is more or less what I wanted. But the original circle is still in place, and while the drag is in progress, the item doesn't follow the mouse cursor.
The QGraphicsSceneDragDropEvent documentation says that pos() should return the cursor position in relation to the view that sent the event, which, unless I got it wrong, shouldn't be (0,0) all the time. Weird.
I've read in a forum post that you can use QDrag::setPixMap() to show something during the drag, and in examples I've seen pictures being set as pixmaps, but how do I make the pixmap just like the graphics item I'm supposed to be dragging?
There is an example with Qt Assistant called the "Drag and Drop Robot Example" which appears to use the QDrag method, I don't know if you've had a look at that already.
edit: Just a quick observation, you appear to be creating a new DragItem in your DropEvent, instead of using the mimeData() of the event itself, and since your item draws itself at 0,0, that might explain why you have a new one appearing at that position regardless of where you drop your DragItem.
When I wrote a graphics dragging thing similar to this, I went about it a slightly different way. Maybe it will help you:
Instead of using the QDrag stuff, I used only the mousePressEvent, mouseReleaseEvent, and mouseMoveEvent functions of QGraphicsItem. The mouse press/release set a flag indicating the drag state, and move followed a process of
call prepareGeometryChange();
update the bounds of the QGraphicsItem (my boundingRect() function returns these bounds. All my graphics item bounds are in QGraphicsScene space)
call update();
Then in my paint() function I draw a shape using the boundingRect().
Sorry I don't have a code sample to share, I'll knock one up if I get time.