1.首先看一下效果
当鼠标移动到字体上时出现控制界面。接下来我们来详细的介绍如何实现的,在文档最后作者也会附上源代码让大家一起探讨。
接上两篇的代码继续写:
QBasicTimer
简单的歌词效果(不能移动,无控件)
我们来看一下代码的改动如何:
在主窗口dialog.h文件中我们新增了eventFilter事件来使得桌面歌词可以移动。
#include
class WigglyWidget;
class subTitleWid;
class Dialog : public QDialog
{
Q_OBJECT
protected:
void paintEvent(QPaintEvent *event)override;
void enterEvent(QEvent *event)override;
void leaveEvent(QEvent *event)override;
bool eventFilter(QObject *, QEvent *)override;
public:
explicit Dialog(QWidget *parent = 0);
subTitleWid * subTitlewid;
WigglyWidget *wigglyWidget;
};
dialog.cpp
我们添加了setAutoFillBackground(false);如果启用,此属性将导致Qt在调用paint事件之前填充小部件的背景。所使用的颜色由小部件调色板中的QPalette::Window color角色定义。因为这个属性与qss设置有冲突。或者将这一行删除。
setAttribute(Qt::WA_TranslucentBackground, true);指示小部件应该具有半透明的背景窗口小部件将有一个alpha通道。设置这个标志会导致WA_NoSystemBackground被设置。在Windows上这个小部件还需要设置Qt::FramelessWindowHint窗口标志。这个标志由小部件的作者设置或清除。
同时重写eventFilter可以使得界面可以被拖动。
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(700, 95);
setWindowTitle(tr("MiMouse"));
//setAutoFillBackground(false);
setAttribute(Qt::WA_TranslucentBackground, true);
setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(0);
wigglyWidget = new WigglyWidget;
wigglyWidget->installEventFilter(this);
subTitlewid = new subTitleWid;
subTitlewid->installEventFilter(this);
subTitlewid->hide();
layout->addWidget(subTitlewid);
layout->addWidget(wigglyWidget);
QString strSubTitle = "测试字幕的效果";
wigglyWidget->setText(strSubTitle);
}
void Dialog::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.fillRect(rect(),QColor(50,50,50,153));
QWidget::paintEvent(event);
}
void Dialog::enterEvent(QEvent *event)
{
Q_UNUSED(event);
/*显示字幕的背景*/
wigglyWidget->setMask(true);
/*显示设置界面*/
subTitlewid->show();
}
void Dialog::leaveEvent(QEvent *event)
{
Q_UNUSED(event);
/*隐藏字幕的背景*/
wigglyWidget->setMask(false);
/*隐藏设置界面*/
subTitlewid->hide();
}
bool Dialog::eventFilter(QObject *obj, QEvent *evt)
{
static QPoint mousePoint;
static bool mousePressed = false;
QMouseEvent *event = static_cast(evt);
if (event->type() == QEvent::MouseButtonPress) {
if (event->button() == Qt::LeftButton) {
mousePressed = true;
mousePoint = event->globalPos() - pos();
return true;
}
} else if (event->type() == QEvent::MouseButtonRelease) {
mousePressed = false;
return true;
} else if (event->type() == QEvent::MouseMove) {
if (mousePressed && (event->buttons() && Qt::LeftButton)) {
move(event->globalPos() - mousePoint);
return true;
}
}
return QObject::eventFilter(obj, evt);
}
因为父窗口在paintEvent中drawRect(rect())将整个窗口都重新绘制了透明区域。所以在标题设置栏就不用再次绘制了。
在子界面(歌词界面)中构造函数中添加 setAttribute(Qt::WA_TranslucentBackground,true);可以使得子窗口透明,在我们想要其显示的时候在在paintEvetn中绘制出界面即可。可能说的比较笼统,具体实现见下面的代码。
总结:
1.当顶层窗口设置 setAttribute(Qt::WA_TranslucentBackground, true);时,会使得背景透明但是控件不透明。这时可以在PainterEvent中用
QPainter painter(this);
painter.fillRect(rect(),QColor(50,50,50,153));
来绘制背景。
2.其子控件如果设置了
setAutoFillBackground(true);//该函数用于设置当窗口作为被包含窗口时, 是否需要绘制背景。注意:QT窗口系统默认状态下, 当一个窗口作为被包含窗口时, 其不再绘制背景, 即使指定了背景绘制参数(如背景颜色、背景图片等)。
这时会不受父控件的背景色影响,从而来绘制属于自己的背景。当然此时也可以来进行 setAttribute(Qt::WA_TranslucentBackground, true);使得自己也背景透明的操作等。
注:若不设置setAutoFillBackground(true);(默认false),则受到父窗口的影响。
源代码