QQuickPaintedItem mouseReleaseEvent gets only called after doubleclick - qt

I've derived a class from QQuickPaintedItem in which I want to handle the mousePressEvent and the mouseReleasEvent (and also the mouseMoveEvent but that is not my prolem now).
The mousePressEvent gets called properly everytime the left mouse button is pressed. But the mouseReleaseEvent gets only called after a double click. What I expected is to get the event everytime the button is released. How can I change this?
This is what I do:
MyView::MyView(QQuickItem *parent):
QQuickPaintedItem(parent)
{
setAcceptedMouseButtons(Qt::LeftButton);
}
void MyView::mousePressEvent(QMouseEvent *evt)
{
//gets called after every single mouse click
qDebug("mousePressEvent");
if(evt->button() == Qt::LeftButton)
{
//do something...
evt->accept();
}
else
{
evt->ignore();
}
QQuickPaintedItem::mousePressEvent(evt);
}
void MyView::mouseReleaseEvent(QMouseEvent *evt)
{
//gets only called when releasing the mouse button after a double click
qDebug("mouseReleaseEvent");
if(evt->button() == Qt::LeftButton)
{
//do something...
evt->accept();
}
else
{
evt->ignore();
}
QQuickPaintedItem::mouseReleaseEvent(evt);
}

So I finally found the solution!
Calling the base class implementation is a bad idea since the base class simply calls ignore() on the event. Here is the base class implementation:
void QWindow::mousePressEvent(QMouseEvent *ev)
{
ev->ignore();
}
void QWindow::mouseReleaseEvent(QMouseEvent *ev)
{
ev->ignore();
}
So this is how it works:
MyView::MyView(QQuickItem *parent):
QQuickPaintedItem(parent)
{
setAcceptedMouseButtons(Qt::LeftButton);
}
void MyView::mousePressEvent(QMouseEvent *evt)
{
//gets called after every single mouse click
qDebug("mousePressEvent");
if(evt->button() == Qt::LeftButton)
{
//do something...
evt->accept();
}
else
{
evt->ignore();
}
//DON'T DO THIS:
//QQuickPaintedItem::mousePressEvent(evt);
}
void MyView::mouseReleaseEvent(QMouseEvent *evt)
{
//now gets called with every mouse release since we don't call the base class any more
qDebug("mouseReleaseEvent");
if(evt->button() == Qt::LeftButton)
{
//do something...
evt->accept();
}
else
{
evt->ignore();
}
//DON'T DO THIS:
//QQuickPaintedItem::mouseReleaseEvent(evt);
}

Related

ChangeEvent blocks QMDISubWIndow

n my App I use a QMDIArea. In this I open now a subclassed MDIChild that has a master class. Inside the master class I set the virtual changeEvent of the subwindow. But if I use this event I cannot move the window in the QMDIArea anymore and the sub window is not create in maximized.
If I remove the Event from the class it works again well. Do I use the Event the wrong way?
MdiChildBase.h
private:
virtual void changeEvent(QEvent * e);
MdiChildBase.cpp
void MdiChildBase::changeEvent(QEvent * e) {
if(e->type() == QEvent::WindowStateChange && this->isActiveWindow()) {
// .. this is now the active window
qDebug("Iam active now");
}
QWidget::changeEvent(e);
}
Ok after reading the docs and try something around the solution for this question is:
void MdiChildBase::changeEvent(QEvent * e) {
QMdiSubWindow::changeEvent(e);
if(e->type() == QEvent::WindowStateChange && this->isActiveWindow()) {
// .. this is now the active window
qDebug("Iam active now");
}
}

graphicsview receives mouse event before the item

I have implemented the panning view on the QGraphicsView, using the mouse move event using
void View::mouseMoveEvent(QMouseEvent* event) {
pan();
QGraphicsView::mouseMoveEvent(event);
}
and in the scene of this view I have added few items where some of the items are resizable, so I implemented
void Item::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if(m_resizeMode)
{
resize();
e->accept();
}
}
I tried to filter the mouse move not to propagate to any further using e->accept()
but my View mouseMove event has been called first , so when ever I tried to resize the item, the view started to pan all the way.
How can I avoid this event propagation from view to scene.
You can call the base class implementation of the QGraphicsView and check if the event is accepted. However I would do this in the mousePressEvent instead of the mouseMoveEvent. After all this is where you determine if you should resize an item or do some panning. This is how I do something similar in my project:
void View::mousePressEvent(QMouseEvent *event)
{
...
QGraphicsView::mousePressEvent(event);
if(event->isAccepted())
move = false;
else
move = true;
}
void View::mouseMoveEvent(QMouseEvent *event)
{
if(!move)
{
QGraphicsView::mouseMoveEvent(event);
return;
}
... // you would do the panning here
QGraphicsView::mouseMoveEvent(event);
}
void View::mouseReleaseEvent(QMouseEvent *event)
{
if(!move)
{
QGraphicsView::mouseReleaseEvent(event);
return;
}
else
{
...
move = false;
}
QGraphicsView::mouseReleaseEvent(event);
}
The view will always receive the mouse event first.
So, in the view, check to see if the mouse is over an item before allowing it to pan by getting the mouse pos in scene coordinates and retrieving the items at that position with QGraphicsScene::items( )

Make QLineEdit detect Tab Key Press event?

I couldn't find anything in the docs. I found one solution that uses PyQt or something, but I'd rather not have to use that. Also, it would be pretty nice if there was a signal for it, but it doesn't look like there is.
1.When you install an event filter as Sam suggested (m_lineEdit->installEventFilter(this);) you need to handle QEvent::KeyPress and check the key to be equal Qt::Key_Tab:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == m_lineEdit) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Tab)
{
//do what you need;
return true;
}
}
// pass the event on to the parent class
return QMainWindow::eventFilter(obj, event);
}
2.Another way to do that is to create a new class inherited from QLineEdit and reimplement keyPressEvent:
void LineEdit::keyPressEvent(QKeyEvent* event)
{
if (keyEvent->key() == Qt::Key_Tab)
{
emit tabPressed();
return;
}
QLineEdit::keyPressEvent(event);
}
You should be able to use QObject::installEventFilter(QObject*) to intercept the key press event. There's an example here: http://qt-project.org/doc/qt-4.8/qobject.html#installEventFilter .

How to save state of a dialog in Qt?

Suppose there are checkboxes, options etc controls in a dialog box, how could I save the state of the dialog in Qt?
Should I use QSettings or something else?
Thanks.
I ran into the same problem.
Googling didn't help too much.
So in the end I wrote my own solution.
I've created a set of functions that read and write the state of each child control of a dialog at creation respectively destruction.
It is generic and can be used for any dialog.
It works like this:
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
QMoMSettings::readSettings(this);
}
Dialog::~Dialog()
{
QMoMSettings::writeSettings(this);
delete ui;
}
...
void QMoMSettings::readSettings(QWidget* window)
{
QSettings settings;
settings.beginGroup(window->objectName());
QVariant value = settings.value("pos");
if (!value.isNull())
{
window->move(settings.value("pos").toPoint());
window->resize(settings.value("size").toSize());
recurseRead(settings, window);
}
settings.endGroup();
}
void QMoMSettings::writeSettings(QWidget* window)
{
QSettings settings;
settings.beginGroup(window->objectName());
settings.setValue("pos", window->pos());
settings.setValue("size", window->size());
recurseWrite(settings, window);
settings.endGroup();
}
void QMoMSettings::recurseRead(QSettings& settings, QObject* object)
{
QCheckBox* checkbox = dynamic_cast<QCheckBox*>(object);
if (0 != checkbox)
{
checkbox->setChecked(settings.value(checkbox->objectName()).toBool());
}
QComboBox* combobox = dynamic_cast<QComboBox*>(object);
if (0 != combobox)
{
combobox->setCurrentIndex(settings.value(combobox->objectName()).toInt());
}
...
foreach(QObject* child, object->children())
{
recurseRead(settings, child);
}
}
void QMoMSettings::recurseWrite(QSettings& settings, QObject* object)
{
QCheckBox* checkbox = dynamic_cast<QCheckBox*>(object);
if (0 != checkbox)
{
settings.setValue(checkbox->objectName(), checkbox->isChecked());
}
QComboBox* combobox = dynamic_cast<QComboBox*>(object);
if (0 != combobox)
{
settings.setValue(combobox->objectName(), combobox->currentIndex());
}
...
foreach(QObject* child, object->children())
{
recurseWrite(settings, child);
}
}
Hope this helps someone after me.
QSettings will work fine for what you need, but you're essentially just serializing the options and reloading them at start up so there's plenty of documentation on doing it in Qt.

Qt making a qmainwindow with videowidget inside displaying an image

I am writing an application using <Phonon/VideoWidget>.
I'd like to have two windows. One is the main window with controls for the video
And the other has the video itself. It will be displayed in another monitor. -fullscreen or not.
How can I make the video window - that can be moved or resizabled - with the video inside?
When not playing any video, the video window should display an image.
In the end I didnt use QStackedWidget, I extended Phonon::VideoWidget and made this class...
Heres the cpp:
MyVideoWidget::MyVideoWidget(QWidget *parent) : Phonon::VideoWidget(parent)
{
label = new QLabel(this);
label->setAutoFillBackground(true);
label->setBackgroundRole(QPalette::Light);
label->setScaledContents(true);
}
void MyVideoWidget::mouseDoubleClickEvent(QMouseEvent* event)
{
if(!this->isFullScreen())
this->enterFullScreen();
else
this->setFullScreen(false);
}
void MyVideoWidget::keyPressEvent(QKeyEvent* event)
{
if(event->key() == Qt::Key_Escape)
{
if(!this->isFullScreen())
this->enterFullScreen();
else
this->setFullScreen(false);
}
}
void MyVideoWidget::enterImageMode(QString imagePath)
{
QPixmap pmap;
pmap.fill(QColor(255, 255, 255));
if(!pmap.load(imagePath))
{
label->setText("Erro ao carregar imagem: "+imagePath);
if(!label->isVisible())
label->show();
return;
}
label->setPixmap(pmap);
if(!label->isVisible())
label->show();
repaint();
}
void MyVideoWidget::enterVideoMode()
{
label->hide();
}
void MyVideoWidget::resizeEvent(QResizeEvent* event)
{
Phonon::VideoWidget::resizeEvent(event);
label->setGeometry(this->geometry());
repaint();
}
MyVideoWidget::~MyVideoWidget()
{
}

Resources