有些窗口在自身最小化时要在桌面上显示一个小浮标,让用户利用这个小浮标进行各种操作(例如迅雷的悬浮窗一样),我试着用QT实现一下这个功能。
PS:本来以为这个功能很简单,却搞了我两个晚上,泪奔。。。
思路:
1:制作一个由一个小图标组成的,可点击,可拖动,背景透明的Widget
2:重载主窗口(在此例子中是QLabel)的changeEvent(详情见代码)
截图:(浅绿色的部分是桌面背景)
主窗体:
小浮标:
代码:
#include <QtGui>
#include <Windows.h>
//
class MinIconWidget : public QWidget
{
Q_OBJECT
private:
QPoint m_CurrentPos;
QPixmap m_Pixmap;
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void paintEvent(QPaintEvent *event);
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
void mouseDoubleClickEvent(QMouseEvent *event);
public:
MinIconWidget(QWidget *parent = 0);
void SetPixmap(const QPixmap &pixmap);
signals:
void DoubleClickedSignal();
};
MinIconWidget::MinIconWidget(QWidget *parent)
: QWidget(parent)
{
//将浮标Widget设置为:顶层窗口;无标题栏;工具条模式;背景透明;无输入焦点
setWindowFlags( Qt::FramelessWindowHint
| Qt::WindowStaysOnTopHint | Qt::Tool );
setAttribute(Qt::WA_TranslucentBackground, true);
setFocusPolicy(Qt::NoFocus);
}
void MinIconWidget::mousePressEvent(QMouseEvent *event)
{
//按住左键移动可以拖动窗口
if(event->button() == Qt::LeftButton)
{
m_CurrentPos = event->globalPos() - frameGeometry().topLeft();
event->accept();
}
}
void MinIconWidget::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() && Qt::LeftButton)
{
move(event->globalPos() - m_CurrentPos);
event->accept();
}
}
void MinIconWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.drawPixmap(0, 0, m_Pixmap);
}
void MinIconWidget::leaveEvent(QEvent *event)
{
//鼠标离开窗口时是普通的指针
setCursor(Qt::ArrowCursor);
}
void MinIconWidget::enterEvent(QEvent *event)
{
//鼠标留在窗口上时是一个手指
setCursor(Qt::PointingHandCursor);
}
void MinIconWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
emit DoubleClickedSignal();
}
void MinIconWidget::SetPixmap(const QPixmap &pixmap)
{
m_Pixmap = pixmap;
update();
}
class MyLabel : public QLabel
{
Q_OBJECT
private:
MinIconWidget *m_minIcon;
protected:
void changeEvent(QEvent *event);
public:
MyLabel(QWidget *parent = 0);
public slots:
void ShowMainWindow();
void HideMainWindow();
};
MyLabel::MyLabel(QWidget *parent /* = 0 */)
: QLabel(parent)
{
m_minIcon = new MinIconWidget;
m_minIcon->SetPixmap( QPixmap("delete.png") );
setWindowFlags( Qt::WindowStaysOnTopHint );
//双击浮动时,隐藏浮标,还原主窗口(这里是一个LABEL)
connect(m_minIcon, SIGNAL(DoubleClickedSignal()), this, SLOT(ShowMainWindow()));
}
void MyLabel::changeEvent(QEvent *event)
{
//重点,窗口最小化时最小化窗口(废话),显示浮标
//窗口还原时,隐藏浮标,还原主窗口(这里是一个LABEL)
if(event->type()==QEvent::WindowStateChange)
{
//changeEvent会在窗口最小化之前调用,如果不加QTimer,
//我们把窗口隐藏了,但是Qt还以为窗口正要最小化,这样就会出错
if(windowState() & Qt::WindowMinimized)
QTimer::singleShot(0, this, SLOT(HideMainWindow()));
else if(windowState() & Qt::WindowNoState)
QTimer::singleShot(0, this, SLOT(ShowMainWindow()));
}
QLabel::changeEvent(event);
}
void MyLabel::ShowMainWindow()
{
m_minIcon->hide();
move( m_minIcon->pos() );
show();
setWindowState(Qt::WindowNoState);
}
void MyLabel::HideMainWindow()
{
hide();
m_minIcon->move( pos() );
m_minIcon->show();
setWindowState(Qt::WindowMinimized);
}
#include "main.moc"
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MyLabel label;
label.setStyleSheet("QLabel{font-size:30px;color:red;}");
label.resize(400, 200);
label.setText("This is a simple demo.");
label.show();
return app.exec();
}