Russian Qt Forum
Май 04, 2024, 07:45 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Всплывающие окна  (Прочитано 12583 раз)
Magvaj
Гость
« : Март 10, 2009, 23:52 »

Пошукал по форуму, но так и не нашёл ни одного вразумительного примера всплывающего окна. Необходимо что-то в стиле Amarok, когда он уведомления показывает. Или же как окошки мессенджеров, когда приходят сообщения.

Может кто реализовывал и поделится советом какие виджеты использовать и в какую сторону копать?
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #1 : Март 11, 2009, 02:36 »

Посмотреть в исходниках?

Можно ещё побаловаться с флагами, например Qt::X11BypassWindowManagerHint может подойти.
Записан
uriel
Гость
« Ответ #2 : Март 11, 2009, 08:50 »

Приделывал подобное уведомление к QMPDClient, ибо очень не хватало. Достаточно создать виджет без указания родительского, установить ему флаги Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint и правильно разместить относительно того места, где оно должно всплывать. Улыбающийся
Записан
kirill
Гость
« Ответ #3 : Март 11, 2009, 09:49 »

Беда в том, что пока оно всплывает юзверь может утащить окно за заголовок.
Приходится отслеживать это и поддергивать, но отставание все равно приличное получается.
Записан
uriel
Гость
« Ответ #4 : Март 11, 2009, 11:57 »

Ну это уже от ситуации зависит. Улыбающийся
Я делал, чтобы при наведении на иконку в трее оно высплывало, а как только курсор вышел за пределы этой иконки - ловко исчезало. А учитывая, что этот виджет не становится активным, то его даже Alt+F7 не возьмёшь.
Да и флаг Qt::FramelessWindowHint вроде бы говорит как раз о том, что рамки у него быть не должно.
Записан
sendevent
Гость
« Ответ #5 : Март 11, 2009, 15:41 »

глянь qutim - похожи на qip'овские, ток посимпотичнее. задумано хорошо, реализовано не особо, но можно взять геометрию слайдинга.
Записан
Magvaj
Гость
« Ответ #6 : Март 11, 2009, 17:39 »

Посмотреть в исходниках?

Можно ещё побаловаться с флагами, например Qt::X11BypassWindowManagerHint может подойти.

а в windows оно работать будет?
Записан
Magvaj
Гость
« Ответ #7 : Март 11, 2009, 17:45 »

глянь qutim - похожи на qip'овские, ток посимпотичнее. задумано хорошо, реализовано не особо, но можно взять геометрию слайдинга.

покопался в коде и сломал мозг. Не понятно у них всё что и откуда.

Решил реализовывать на основе QFrame с флагом Qt::ToolTip.
« Последнее редактирование: Март 11, 2009, 18:16 от Magvaj » Записан
sendevent
Гость
« Ответ #8 : Март 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 и юай приводить лень, будут вопросы - постараюсь ответить=)
Записан
Magvaj
Гость
« Ответ #9 : Март 15, 2009, 12:12 »

sendevent, благодарю за код... в принципе- то что я хотел, только ввиду срочности и напора со стороны начальства пришлось ночами в темпе марша реализовывать самому.

Удалось выяснить факт: виджет не перекрывается панелью задач только в случае если он будет отображаться в виде окна на панельке. В остальных случаях он всегда перекрывает её.

Реализовал класс для виджета ToolTip и управляющий для нормальной анимации и перепозиционирования виджетов в случае удаления некоторых. Так же есть реакции на различные действия со стороны устройств ввода. Класс прекрасно пашет под Win и Lin. Компилится без требований спецефичных классов. Если кому потребуется- пишите в личку- скину код ;-) (сюда выложить не могу по понятным причинам)
Записан
kirill
Гость
« Ответ #10 : Март 15, 2009, 18:34 »

Ну это уже от ситуации зависит. Улыбающийся
Я делал, чтобы при наведении на иконку в трее оно высплывало, а как только курсор вышел за пределы этой иконки - ловко исчезало. А учитывая, что этот виджет не становится активным, то его даже Alt+F7 не возьмёшь.
Да и флаг Qt::FramelessWindowHint вроде бы говорит как раз о том, что рамки у него быть не должно.

Я не про рамку у подсказки, а у того окна к которому оно привязано.
Если показывать в трее, то понятно что этой проблемы нет.
А если привязывать к онку, которое можно елозить, то отставание.
Записан
AlekseyK
Гость
« Ответ #11 : Сентябрь 23, 2009, 19:18 »

Я делал, чтобы при наведении на иконку в трее оно высплывало, а как только курсор вышел за пределы этой иконки - ловко исчезало.
А можно поподробнее, пожалуйста как это сделать?

Я переопределил mouseMoveEvent(QMouseEvent *event) в моём всплывающем виджете, но что-то он на движения мыши вообще никак не реагирует (смотрю через отладчик), не говоря о том уже, чтобы спрятаться:

Код
C++ (Qt)
void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
   QWidget::mouseMoveEvent(event);
   if(event->type() == QEvent::Leave)
       hide();
}

Нужно как-то по другому делать?
Записан
uriel
Гость
« Ответ #12 : Октябрь 07, 2009, 17:59 »

Извиняюсь, вопрос увидел только сейчас. Видимо, не помешает взять в привычку проверять ответы на свои сообщения при каждом посещении. Улыбающийся
Оно всё ещё актуально?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.114 секунд. Запросов: 23.