Buttons appear when hover over media player
-
Hi,
I am using QMediaPlayer and QVideoWidget to create a media player to show a couple of videos in my application. I followed the following tutorial to create play, pause and stop buttons and it is working.
[https://doc.qt.io/qt-5/qtmultimedia-multimediawidgets-player-example.html](link url)
However, I want my play, pause and stop buttons to be shown on media player when user hover over media player and hidden when mouse is not on the media player similar to Youtube:
When I use the enterevent and the leaveevent of the QVideoWidget, if I get cursor over the button created by the enterevent of the video widget, it starts to call leaveevent and enterevent again and again, the buttons are flicking.
How can I do this properly?
l really appreciate any help you can provide. -
@mehmety888
Hi,You can do it with event filter like below. You should catch the mouse position in the frame or in the view widget. Also you should make the m_p_button_frame as a Tool window like you did in your constructor. You do not need to have enterEvent and leaveEvent. You should delete them.
bool VideoWidget::eventFilter(QObject *in_p_watched, QEvent *in_p_event) { if(this == in_p_watched || m_p_button_frame == in_p_watched) { QMouseEvent *p_mouse_event = dynamic_cast<QMouseEvent *>(in_p_event); if (Q_NULLPTR != p_mouse_event) { QPoint mouse_position = p_mouse_event->pos(); QRect rect = this->rect(); rect.setX(rect.x()+10); rect.setY(rect.y()+10); rect.setWidth(rect.width()-20); rect.setHeight(rect.height()-20); if (false == rect.contains(mouse_position)) { m_p_button_frame->hide(); } else if (true == this->rect().contains(mouse_position)) { QPoint global_point = QWidget::mapToGlobal(this->pos()); m_p_button_frame->setGeometry(global_point.x()+10,global_point.y(),200,50); m_p_button_frame->show(); } } } return QObject::eventFilter(in_p_watched, in_p_event); }
-
My code is like below:
VideoWidget.h
#include <QVideoWidget> class QPushButton; class QFrame; class VideoView; class VideoWidget: public QVideoWidget { Q_OBJECT Q_DISABLE_COPY(VideoWidget) public: explicit VideoWidget(QWidget *in_p_parent = Q_NULLPTR); protected: void enterEvent(QEvent *in_p_event) Q_DECL_OVERRIDE; void leaveEvent(QEvent *in_p_event) Q_DECL_OVERRIDE; private: QFrame *m_p_button_frame = Q_NULLPTR; QPushButton *m_p_add_play_button = Q_NULLPTR; QPushButton *m_p_add_stop_button = Q_NULLPTR; };
VideoWidget.cpp:
#include "VideoWidget.h" #include <QPushButton> #include <QFrame> #include <QHBoxLayout> #include "VideoView.h" #include <QMouseEvent> #include <QEvent> #include <QApplication> VideoWidget::VideoWidget(QWidget *in_p_parent) : QVideoWidget(in_p_parent) { qApp->installEventFilter(this); setMouseTracking(true); setAttribute(Qt::WA_Hover, true); m_p_button_frame = new QFrame(this); QHBoxLayout *p_layout = new QHBoxLayout; m_p_button_frame->setLayout(p_layout); m_p_add_play_button = new QPushButton(m_p_button_frame); m_p_add_play_button->setText("Play"); m_p_add_stop_button = new QPushButton(m_p_button_frame); m_p_add_stop_button->setText("Stop"); p_layout->addWidget(m_p_add_play_button); p_layout->addWidget(m_p_add_stop_button); VideoView *p_parent = dynamic_cast<VideoView *>(in_p_parent); connect(m_p_add_play_button, &QPushButton::clicked, p_parent, &VideoView::slotPlayVideo); connect(m_p_add_stop_button, &QPushButton::clicked, p_parent, &VideoView::slotStopVideo); m_p_button_frame->setAttribute(Qt::WA_ShowWithoutActivating, true); m_p_button_frame->setAttribute( Qt::WA_TranslucentBackground ); Qt::WindowFlags flags = Qt::Tool; flags |= Qt::FramelessWindowHint; flags |= Qt::WindowStaysOnTopHint; m_p_button_frame->setWindowFlags(flags); } void VideoWidget::enterEvent(QEvent *in_p_event) { QVideoWidget::enterEvent(in_p_event); QPoint global_point = QWidget::mapToGlobal(this->pos()); m_p_button_frame->setGeometry(global_point.x(),global_point.y(),100,30); m_p_button_frame->show(); } void VideoWidget::leaveEvent(QEvent *in_p_event) { QVideoWidget::leaveEvent(in_p_event); m_p_button_frame->hide(); }
-
@mehmety888
Why do you set the button frame to be a tool window? That makes it a window, not a child widget, so this mouse thing won't work. -
Hi,
Why are you installing an event filter ?
Are you sure the hover related methods are called ?
What if you do not set your custom class as parent of your frame ? -
@mehmety888 said in Buttons appear when hover over media player:
I removed Tool flag, but pushbuttons are not visible now.
I think this is simply because when it is not a window any more, you shouldn't set its geometry by global coordinate, but its parent's coordinate, so
mapToGlobal
is not needed.And there're lots of code from your post I don't think is necessary:
theseqApp->installEventFilter(this); setMouseTracking(true); setAttribute(Qt::WA_Hover, true);
and these all
m_p_button_frame->setAttribute(Qt::WA_ShowWithoutActivating, true); m_p_button_frame->setAttribute( Qt::WA_TranslucentBackground ); Qt::WindowFlags flags = Qt::Tool; flags |= Qt::FramelessWindowHint; flags |= Qt::WindowStaysOnTopHint; m_p_button_frame->setWindowFlags(flags);
-
@SGaist Hi,
I was also trying to do it using event filter, I forgot to remove it.
I also tried using hover, it is not necessary now, I will remove it.If I don't set my custom class as parent, and I get cursor over the button created by the enterevent of the video widget, it starts to call leaveevent and enterevent again and again, the buttons are flicking.
-
@Bonnie Thank you for your feedback.
When I do the changes you mentioned, enterevent and leaveevent works fine, but video gets in front of pushbuttons and frame unless I click on frame position. Then it plays / stops video (buttons and frame are not visible)
-
@mehmety888
Hi,You can do it with event filter like below. You should catch the mouse position in the frame or in the view widget. Also you should make the m_p_button_frame as a Tool window like you did in your constructor. You do not need to have enterEvent and leaveEvent. You should delete them.
bool VideoWidget::eventFilter(QObject *in_p_watched, QEvent *in_p_event) { if(this == in_p_watched || m_p_button_frame == in_p_watched) { QMouseEvent *p_mouse_event = dynamic_cast<QMouseEvent *>(in_p_event); if (Q_NULLPTR != p_mouse_event) { QPoint mouse_position = p_mouse_event->pos(); QRect rect = this->rect(); rect.setX(rect.x()+10); rect.setY(rect.y()+10); rect.setWidth(rect.width()-20); rect.setHeight(rect.height()-20); if (false == rect.contains(mouse_position)) { m_p_button_frame->hide(); } else if (true == this->rect().contains(mouse_position)) { QPoint global_point = QWidget::mapToGlobal(this->pos()); m_p_button_frame->setGeometry(global_point.x()+10,global_point.y(),200,50); m_p_button_frame->show(); } } } return QObject::eventFilter(in_p_watched, in_p_event); }