Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: l_a_m от Май 13, 2010, 13:04



Название: Тень в Qt
Отправлено: l_a_m от Май 13, 2010, 13:04
Доброго времени суток Ув. Коллеги!
Есть ли в Qt возможность простой реализации отбрасывания тени у диалоговых окон? (проще чем ритуальные танцы с бубном вокруг прозрачности в png)

Версия Qt:  4.6.2; ОС: Windows XP (но желательно, что бы вариант решения был кроссплатформенным и не зависели от ОС)


Название: Re: Тень в Qt
Отправлено: GreatSnake от Май 13, 2010, 13:36
Цитировать
Есть ли в Qt возможность простой реализации отбрасывания тени у диалоговых окон?
Нет, т.к. отрисовкой стандартных декораций окна Qt не занимается - не её это дело.


Название: Re: Тень в Qt
Отправлено: l_a_m от Май 13, 2010, 14:01
Цитировать
Есть ли в Qt возможность простой реализации отбрасывания тени у диалоговых окон?
Нет, т.к. отрисовкой стандартных декораций окна Qt не занимается - не её это дело.
Понятно... тогда, кто может ткнуть носом в кроссплатформенный вариант отрисовки красивостей?


Название: Re: Тень в Qt
Отправлено: GreatSnake от Май 13, 2010, 14:10
Есть 2 варианта - Aero для винды и Compiz для X11.
Если вы сами будете это делать, то в лучшем случае получите глючный тормоз.
Поэтому рекомендую забить на эти "красивости".


Название: Re: Тень в Qt
Отправлено: Alex Custov от Май 13, 2010, 17:12
кроссплатформенный вариант отрисовки красивостей?

боюсь такого нет


Название: Re: Тень в Qt
Отправлено: nixman05 от Май 13, 2010, 18:01
В Qt начиная с 4.6 появились классы QGraphicsEffect.

В часности QGraphicsDropShadowEffect:
http://doc.trolltech.com/4.6/qgraphicsdropshadoweffect.html (http://doc.trolltech.com/4.6/qgraphicsdropshadoweffect.html)


Название: Re: Тень в Qt
Отправлено: GreatSnake от Май 13, 2010, 19:36
Человек спрашивал про "возможность простой реализации отбрасывания тени у диалоговых окон".
Причём здесь QGraphicsDropShadowEffect?


Название: Re: Тень в Qt
Отправлено: nixman05 от Май 13, 2010, 19:44
Человек спрашивал про "возможность простой реализации отбрасывания тени у диалоговых окон".
Причём здесь QGraphicsDropShadowEffect?

Код
C++ (Qt)
QDialog *dialog=new QDialog();
QGraphicsDropShadowEffect *effect=new QGraphicsDropShadowEffect();
dialog->setGraphicsEffect(effect);
dialog->show();
 


Название: Re: Тень в Qt
Отправлено: GreatSnake от Май 13, 2010, 19:48
И работает? И везде?
Не верю.


Название: Re: Тень в Qt
Отправлено: l_a_m от Май 14, 2010, 08:55
Человек спрашивал про "возможность простой реализации отбрасывания тени у диалоговых окон".
Причём здесь QGraphicsDropShadowEffect?

Код
C++ (Qt)
QDialog *dialog=new QDialog();
QGraphicsDropShadowEffect *effect=new QGraphicsDropShadowEffect();
dialog->setGraphicsEffect(effect);
dialog->show();
 

Добрый день, попробовал предложенный вами вариант реализации, так и не смог заставить диалог отбрасывать тень :-(
Есть ли ещё какие нибудь варианты?

Получилось реализовать описанный выше метод, для кнопки - она действительно отбрасывает тень на форму, а вот как бы сделать такое же но с диалогом?


Название: Re: Тень в Qt
Отправлено: GreatSnake от Май 14, 2010, 09:36
Вот упёртый человек. Говорят же - средствами Qt или какого-либо другого API не получится!
Вы сами подумайте - даже если вы сможете каким-либо чудесным образом отрисовывать тень, то как вы будете доставлять нажатие мыши на участке тени, который принадлежит другому окну?! Единственный, кто сможет сделать это - это оконный менеджер.


Название: Re: Тень в Qt
Отправлено: l_a_m от Май 14, 2010, 10:00
Вот упёртый человек. Говорят же - средствами Qt или какого-либо другого API не получится!
Вы сами подумайте - даже если вы сможете каким-либо чудесным образом отрисовывать тень, то как вы будете доставлять нажатие мыши на участке тени, который принадлежит другому окну?! Единственный, кто сможет сделать это - это оконный менеджер.

:-) эх... уговорили... забиваю большой и толстый на красивости :-) напишем в требованиях к программе ОС: Vista/7 и теоретически будет счастье, а под никсами, я думаю, там не до красивостей, либо бубен в комплекте прилагать :-)


Название: Re: Тень в Qt
Отправлено: BRE от Май 14, 2010, 10:19
а под никсами, я думаю, там не до красивостей, либо бубен в комплекте прилагать :-)
Если человеку нужны будут красивости, он спокойно поставит нужные пакеты и натыкает нужных галочек.  :)
... и Венда7, на его фоне, будет выглядеть страшненьким уродцем...  ;)


Название: Re: Тень в Qt
Отправлено: offitserov от Октябрь 05, 2010, 18:43
Как оказалось в результате более близкого рассмотрения тень в Qt как для диалоговых окон так и для любого top-level widget реализуется довольно просто без танцев с бубном и без новых навороченных возможностей.
Да и почему-бы это было невозможным? В Qt есть все для этого средства...
(Qt::FramelessWindowHint, Qt::SplashScreen, QWidget::setMask(), QWidget::setOpacity()).  ;D


Название: Re: Тень в Qt
Отправлено: GreatSnake от Октябрь 05, 2010, 18:51
Рабочий пример в студию!


Название: Re: Тень в Qt
Отправлено: Igors от Октябрь 05, 2010, 19:03
Как оказалось в результате более близкого рассмотрения тень в Qt как для диалоговых окон так и для любого top-level widget реализуется довольно просто без танцев с бубном и без новых навороченных возможностей.
Да и почему-бы это было невозможным? В Qt есть все для этого средства...
(Qt::FramelessWindowHint, Qt::SplashScreen, QWidget::setMask(), QWidget::setOpacity()).  ;D
Ну "замах" явно рублевый  :) А вот какой будет "бросок" - не копеечный ли? Показываем..


Название: Re: Тень в Qt
Отправлено: offitserov от Октябрь 10, 2010, 19:40
Доброго времени суток.
Простите что сразу не запостил пример, не было времени.
Также сразу хочу оговориться:
1. Пример не показывает как сделать передачу сообщений окнам под тенью, это не кроссплатформенный заход.
2. Не тестировал под Линуксом, судя по отзывам могут быть проблемы с прозрачностью.
3. Таже пример есть просто концепт, призванный показать что возможность нарисовать тень есть и работает "as-is". Например красивее тень рисовать градиентами и обрабатывать некоторые события по-чище.
Код:
#include <QtGui>
//------------------------------------------------------------------
class ShadowWidget : public QWidget
{
public:
    ShadowWidget(QWidget * nestedWidget, QWidget *parent = 0, int shadowWidth = 10, int radius = 5)
        : QWidget(parent, Qt::SplashScreen)
        , m_nested(nestedWidget)
        , m_shadowWidth(shadowWidth)
        , m_radius(radius)
    {
        this->setWindowOpacity(0.4);
    }

    void updateSize()
    {
        move(m_nested->pos());
        setFixedSize(m_nested->size().width() + m_shadowWidth, m_nested->size().height() + m_shadowWidth);
    }

protected:
    void paintEvent       (QPaintEvent  *event)
    {
        Q_UNUSED(event);
        QPainter painter(this);
        painter.fillRect(rect(), QBrush(Qt::black));
    }

    void resizeEvent      (QResizeEvent *event)
    {
        qDebug() << Q_FUNC_INFO << " pos() = " << pos();
        Q_UNUSED(event);
        QBitmap bitmap(rect().size());
        bitmap.fill(Qt::white);
        bitmap.createMaskFromColor(Qt::white, Qt::MaskOutColor);
        QPainter painter(&bitmap);
       
        QPainterPath opaquePath;
        opaquePath.addRoundRect(rect().adjusted(m_shadowWidth, m_shadowWidth, 0, 0), m_shadowWidth, m_shadowWidth);
        painter.fillPath(opaquePath, Qt::black);

        QPainterPath transparentPath;
        transparentPath.addRoundRect(rect().adjusted(0, 0, -m_shadowWidth, -m_shadowWidth), m_radius, m_radius);
        painter.fillPath(transparentPath, Qt::white);
       
        setMask(bitmap);
    }

private:
    QWidget *m_nested;
    int m_shadowWidth;
    int m_radius;
};
//------------------------------------------------------------------
class CustomDialog : public QDialog
{
Q_OBJECT
public:

    CustomDialog(QWidget *parent = 0, int radius = 5)
        : QDialog(parent, Qt::FramelessWindowHint)
        , m_shadow(new ShadowWidget(this, parent))
        , m_radius(radius)
    {
    }

    ~CustomDialog()
    {
        delete m_shadow;
    }
   
protected:
/// event handlers
    void mousePressEvent  (QMouseEvent  *event)
    {
        const bool leftButtonPressed(event->button() == Qt::LeftButton);
        if (!leftButtonPressed || !rect().contains(event->pos()))
            return;
        m_moving = true;
        m_dragPosition = event->globalPos() - frameGeometry().topLeft();
        event->accept();
        return;
    }

    void mouseReleaseEvent(QMouseEvent  *event)
    {
        Q_UNUSED(event);
        m_moving = false;
    }

    void mouseMoveEvent   (QMouseEvent  *event)
    {
        if (!m_moving)
            return;

        move(event->globalPos() - m_dragPosition);
        m_shadow->updateSize();
        m_dragPosition = event->globalPos() - frameGeometry().topLeft();
        event->accept();
    }

void paintEvent       (QPaintEvent  *event)
    {
        Q_UNUSED(event);
        QPainter painter(this);
        QPen pen(QColor(Qt::green), 3);
        painter.setPen(pen);
        painter.drawRoundRect(rect().adjusted(0, 0, -1, -1), m_radius, m_radius);
        m_shadow->updateSize();
        m_shadow->show();
    }

    void resizeEvent      (QResizeEvent *event)
    {
        Q_UNUSED(event);
        QBitmap bitmap(rect().size());
        bitmap.fill(Qt::white);
        bitmap.createMaskFromColor(Qt::white, Qt::MaskOutColor);
        QPainter painter(&bitmap);
        painter.setPen(Qt::black);
        QPainterPath path;
        path.addRoundRect(rect(), m_radius, m_radius);
        painter.fillPath(path, Qt::black);
        setMask(bitmap);
        m_shadow->update();
    }

private:

bool m_moving;
QPoint           m_dragPosition;
    ShadowWidget *m_shadow;
    int m_radius;
};
//------------------------------------------------------------------
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    CustomDialog dialog;
    dialog.setFixedSize(100, 60);
    dialog.show();
    app.exec();
}

#include "main.moc"
Пользуйтесь на здоровье. :)


Название: Re: Тень в Qt
Отправлено: SASA от Октябрь 11, 2010, 10:35
Код:
void paintEvent       (QPaintEvent  *event)
{
m_shadow->updateSize();
m_shadow->show();
}

void resizeEvent      (QResizeEvent *event)
{
m_shadow->update();
}
А Зачем эти строки?