Доброго времени суток.
Простите что сразу не запостил пример, не было времени.
Также сразу хочу оговориться:
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"
Пользуйтесь на здоровье.