Название: Всплывающие окна
Отправлено: Magvaj от Март 10, 2009, 23:52
Пошукал по форуму, но так и не нашёл ни одного вразумительного примера всплывающего окна. Необходимо что-то в стиле Amarok, когда он уведомления показывает. Или же как окошки мессенджеров, когда приходят сообщения.
Может кто реализовывал и поделится советом какие виджеты использовать и в какую сторону копать?
Название: Re: Всплывающие окна
Отправлено: Alex Custov от Март 11, 2009, 02:36
Посмотреть в исходниках?
Можно ещё побаловаться с флагами, например Qt::X11BypassWindowManagerHint может подойти.
Название: Re: Всплывающие окна
Отправлено: uriel от Март 11, 2009, 08:50
Приделывал подобное уведомление к QMPDClient, ибо очень не хватало. Достаточно создать виджет без указания родительского, установить ему флаги Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint и правильно разместить относительно того места, где оно должно всплывать. :)
Название: Re: Всплывающие окна
Отправлено: kirill от Март 11, 2009, 09:49
Беда в том, что пока оно всплывает юзверь может утащить окно за заголовок. Приходится отслеживать это и поддергивать, но отставание все равно приличное получается.
Название: Re: Всплывающие окна
Отправлено: uriel от Март 11, 2009, 11:57
Ну это уже от ситуации зависит. :) Я делал, чтобы при наведении на иконку в трее оно высплывало, а как только курсор вышел за пределы этой иконки - ловко исчезало. А учитывая, что этот виджет не становится активным, то его даже Alt+F7 не возьмёшь. Да и флаг Qt::FramelessWindowHint вроде бы говорит как раз о том, что рамки у него быть не должно.
Название: Re: Всплывающие окна
Отправлено: sendevent от Март 11, 2009, 15:41
глянь qutim - похожи на qip'овские, ток посимпотичнее. задумано хорошо, реализовано не особо, но можно взять геометрию слайдинга.
Название: Re: Всплывающие окна
Отправлено: Magvaj от Март 11, 2009, 17:39
Посмотреть в исходниках?
Можно ещё побаловаться с флагами, например Qt::X11BypassWindowManagerHint может подойти.
а в windows оно работать будет?
Название: Re: Всплывающие окна
Отправлено: Magvaj от Март 11, 2009, 17:45
глянь qutim - похожи на qip'овские, ток посимпотичнее. задумано хорошо, реализовано не особо, но можно взять геометрию слайдинга.
покопался в коде и сломал мозг. Не понятно у них всё что и откуда. Решил реализовывать на основе QFrame с флагом Qt::ToolTip.
Название: Re: Всплывающие окна
Отправлено: sendevent от Март 11, 2009, 19:05
по поводу перекрытия панелью задач - хз :) выдрал из проекта, на компелябельность не проверял, но, думаю, в общих чертах понятно и за скелет взять можно будет: systraymessage.h #include <QWidget> #include <QTimer>
#include "ui_systraymessage.h" class SysTrayMessage : public QWidget { Q_OBJECT public: SysTrayMessage( int, int, int, unsigned int, int, int, QWidget *parent = 0); virtual ~SysTrayMessage(); bool m_bIs1stTrayWindow; void showTrayMessage(); void setHtml( const QString & ); void setColor( const QColor& color ); void setTitle( const QString & ); inline int getStackPosition() const { return m_iStackPos; } protected: virtual void construct( int iWidthPx, int iHeightPx, int iTimeS, unsigned int uiScreenCorner, int iSlideStyle, int iStackPos ); protected slots: void slideVerticallyUp(); void slideVerticallyDown(); void slideHorizontallyRight(); void slideHorizontallyLeft(); public slots: void close(); private: Ui::SysTrayMessageUi ui; unsigned int m_uiScreenCorner; int m_iSlideStyle; int m_iTTLSecs; int m_iStackPos; int fromX; int fromY; int m_iWidth, m_iHeigth; QColor m_color; QTimer m_timer; QPoint m_ptPrevPos, m_ptSlideDst; void slide(); void calcCoords(); signals: void signalClosed(); };
systraymessage.cpp #include "systraymessage.h"
#include <QPalette> #include <QColor> #include <QDesktopWidget>
SysTrayMessage::SysTrayMessage( int width, int height, int t, unsigned int pos, int st, int psInStack, QWidget *parent) :QWidget(parent) { construct( width, height, t, pos, st, psInStack ); }
/*virtual*/ void SysTrayMessage::construct( int iWidthPx, int iHeightPx, int iTimeS, unsigned int uiScreenCorner, int iSlideStyle, int iStackPos ) { ui.setupUi(this); fromX = 0; fromY = 0; m_iWidth = iWidthPx; m_iHeigth = iHeightPx; resize( QSize( m_iWidth, m_iHeigth ) ); m_uiScreenCorner uiScreenCorner; m_iSlideStyle = iSlideStyle; m_iTTLSecs = iTimeS; m_iStackPos = iStackPos; m_bIs1stTrayWindow = true; m_ptPrevPos = QPoint( 0, 0 ); m_timer.setInterval( m_iTTLSecs*1000 ); connect( &m_timer, SIGNAL( timeout() ), this, SLOT( close() ) ); #if defined(Q_OS_MAC) setWindowFlags(windowFlags() | Qt::FramelessWindowHint); #else setWindowFlags( Qt::CustomizeWindowHint|Qt::WindowStaysOnTopHint|Qt::ToolTip ); #endif } SysTrayMessage::~SysTrayMessage() { }
void SysTrayMessage::showTrayMessage() { show(); calcCoords(); m_timer.start(); slide(); }
void SysTrayMessage::calcCoords() { QDesktopWidget desktopSize; QRect geometry = desktopSize.availableGeometry(); resize( m_iWidth, m_iHeigth ); switch(m_uiScreenCorner) { case ScreenCornerPosition::TopLeft: m_ptSlideDst = QPoint( geometry.left(), geometry.top() + (m_iStackPos - 1) * m_iHeigth ); break; case ScreenCornerPosition::TopRight: m_ptSlideDst = QPoint( geometry.right() - m_iWidth, geometry.top() + (m_iStackPos - 1) * m_iHeigth ); break; case ScreenCornerPosition::BottomLeft: m_ptSlideDst = QPoint( geometry.left(), geometry.bottom() - m_iStackPos * m_iHeigth ); break; default: m_ptSlideDst = QPoint( geometry.right() - m_iWidth, geometry.bottom() - m_iStackPos * m_iHeigth ); } }
void SysTrayMessage::close() { //-- custom process... ... QWidget::close(); emit signalClosed(); }
void SysTrayMessage::slide() { switch (m_iSlideStyle) { case 1: if( m_uiScreenCorner == ScreenCornerPosition::TopLeft || m_uiScreenCorner == ScreenCornerPosition::TopRight ) { fromX = m_ptSlideDst.x(); fromY = m_ptSlideDst.y()-height(); move( fromX, fromY ); show(); slideVerticallyDown(); } else if( m_uiScreenCorner == ScreenCornerPosition::BottomLeft || m_uiScreenCorner == ScreenCornerPosition::BottomRight) { fromX = m_ptSlideDst.x(); fromY = m_ptSlideDst.y() + height(); move( fromX, fromY ); show(); slideVerticallyUp(); } break; case 0: if( m_uiScreenCorner == ScreenCornerPosition::TopLeft || m_uiScreenCorner == ScreenCornerPosition::BottomLeft ) { fromX = m_ptSlideDst.x() - width(); fromY = m_ptSlideDst.y(); move( fromX, fromY ); show(); slideHorizontallyRight(); } else if( m_uiScreenCorner == ScreenCornerPosition::TopRight || m_uiScreenCorner == ScreenCornerPosition::BottomRight ) { fromX = m_ptSlideDst.x() + width(); fromY = m_ptSlideDst.y(); move( fromX, fromY ); show(); slideHorizontallyLeft(); } break; default: move( m_ptSlideDst ); show(); } }
void SysTrayMessage::slideVerticallyUp() { fromY -= 5;
if (fromY >= m_ptSlideDst.y()) { move(m_ptSlideDst.x(), fromY); QTimer::singleShot(10, this, SLOT(slideVerticallyUp())); } }
void SysTrayMessage::slideVerticallyDown() { fromY += 5; if (fromY <= m_ptSlideDst.y()) { move(m_ptSlideDst.x(), fromY); QTimer::singleShot(10, this, SLOT(slideVerticallyDown())); } }
void SysTrayMessage::slideHorizontallyRight() { fromX += 5; if (fromX <= m_ptSlideDst.x()) { move(fromX, m_ptSlideDst.y()); QTimer::singleShot(10, this, SLOT(slideHorizontallyRight())); } }
void SysTrayMessage::slideHorizontallyLeft() { fromX -= 5; if (fromX >= m_ptSlideDst.x()) { move(fromX, m_ptSlideDst.y()); QTimer::singleShot(10, this, SLOT(slideHorizontallyLeft())); } }
void SysTrayMessage::setHtml( const QString& html ) { ui.textDisplay->setHtml( html ); }
void SysTrayMessage::setColor( const QColor& color ) { m_color = color; this->setStyleSheet( QString( "background-color: rgb(%1, %2, %3);" ) .arg( m_color.red() ).arg( m_color.green() ).arg( m_color.blue() ) ); }
void SysTrayMessage::setTitle( const QString &title ) { ui.label->setText( title ); ui.label->setToolTip( title ); }
использование: SysTrayMessage* SysTrayMessageFactory::createMessage( const QString& title, const QString& msg, bool delOnClose ) { if ( !m_b1stMsgShown ) { m_b1stMsgShown = true; m_iMsgCellInStack = 1; } SysTrayMessage *trayMessageWindow = new SysTrayMessage( m_iMsgWidth, m_iMsgHeight, m_iMsgTTLSecs, m_uiMsgScrCorner, m_iMsgStyle, m_iMsgCellInStack ); trayMessageWindow->m_bIs1stTrayWindow = m_b1stMsgShown; trayMessageWindow->setColor( m_color ); trayMessageWindow->setTitle( title ); trayMessageWindow->setHtml( msg ); if( delOnClose ) trayMessageWindow->setAttribute( Qt::WA_DeleteOnClose ); connect( trayMessageWindow, SIGNAL( signalClosed() ), this, SLOT( slotUpdateSysTrayMessagesList() ) ); if ( ( ++m_iMsgCellInStack ) > 5) m_iMsgCellInStack = 5; trayMessagesList.append( trayMessageWindow ); return trayMessageWindow; }
void SysTrayMessageFactory::slotUpdateSysTrayMessagesList() { SysTrayMessage *tempWindow = qobject_cast<SysTrayMessage*>( sender() ); if( tempWindow ) { if( !trayMessagesList.count() ) {//-- smth wrong :-[ disconnect( tempWindow, SIGNAL( signalClosed() ), this, SLOT( slotUpdateSysTrayMessagesList() ) ); tempWindow->close(); return; } else { if ( tempWindow->m_bIs1stTrayWindow ) m_b1stMsgShown = false; int index = trayMessagesList.indexOf( tempWindow ); if( index >= 0 ) { trayMessagesList.takeAt( index ); qDebug( "SysTrayMessageFactory::slotUpdateSysTrayMessagesList: msg removed!" ); m_iMsgCellInStack--; } } qDebug( "SysTrayMessageFactory::slotUpdateSysTrayMessagesList: msges amount: %d", trayMessagesList.count() ); } }
SysTrayMessageFactory и юай приводить лень, будут вопросы - постараюсь ответить=)
Название: Re: Всплывающие окна
Отправлено: Magvaj от Март 15, 2009, 12:12
sendevent, благодарю за код... в принципе- то что я хотел, только ввиду срочности и напора со стороны начальства пришлось ночами в темпе марша реализовывать самому.
Удалось выяснить факт: виджет не перекрывается панелью задач только в случае если он будет отображаться в виде окна на панельке. В остальных случаях он всегда перекрывает её.
Реализовал класс для виджета ToolTip и управляющий для нормальной анимации и перепозиционирования виджетов в случае удаления некоторых. Так же есть реакции на различные действия со стороны устройств ввода. Класс прекрасно пашет под Win и Lin. Компилится без требований спецефичных классов. Если кому потребуется- пишите в личку- скину код ;-) (сюда выложить не могу по понятным причинам)
Название: Re: Всплывающие окна
Отправлено: kirill от Март 15, 2009, 18:34
Ну это уже от ситуации зависит. :) Я делал, чтобы при наведении на иконку в трее оно высплывало, а как только курсор вышел за пределы этой иконки - ловко исчезало. А учитывая, что этот виджет не становится активным, то его даже Alt+F7 не возьмёшь. Да и флаг Qt::FramelessWindowHint вроде бы говорит как раз о том, что рамки у него быть не должно.
Я не про рамку у подсказки, а у того окна к которому оно привязано. Если показывать в трее, то понятно что этой проблемы нет. А если привязывать к онку, которое можно елозить, то отставание.
Название: Re: Всплывающие окна
Отправлено: AlekseyK от Сентябрь 23, 2009, 19:18
Я делал, чтобы при наведении на иконку в трее оно высплывало, а как только курсор вышел за пределы этой иконки - ловко исчезало. А можно поподробнее, пожалуйста как это сделать? Я переопределил mouseMoveEvent(QMouseEvent *event) в моём всплывающем виджете, но что-то он на движения мыши вообще никак не реагирует (смотрю через отладчик), не говоря о том уже, чтобы спрятаться: C++ (Qt) void MyWidget::mouseMoveEvent(QMouseEvent *event) { QWidget::mouseMoveEvent(event); if(event->type() == QEvent::Leave) hide(); }
Нужно как-то по другому делать?
Название: Re: Всплывающие окна
Отправлено: uriel от Октябрь 07, 2009, 17:59
Извиняюсь, вопрос увидел только сейчас. Видимо, не помешает взять в привычку проверять ответы на свои сообщения при каждом посещении. :) Оно всё ещё актуально?
|