很多端游的启动器客户端都是异形窗口,无边框,自绘并重写了最小化、最大化、关闭按钮。本文具体讲一下实现。
步骤:
1,设置窗口透明度、窗口无边框样式、窗口背景透明。
2,准备ps过的带透明通道的不规则png图片,设置为窗口背景。
3,重写鼠标事件实现窗口移动。
看效果:
背景是EA大作《镜之边缘》
上代码:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_btn1_clicked();
void on_btn2_clicked();
private:
Ui::MainWindow *ui;
bool m_Drag; //记录鼠标是否按下
QPoint m_DragPosition;//记录鼠标位置
//重写三个鼠标事件来实现窗口移动
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMouseEvent>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设置属性(如果为了统一管理样式,便于子窗口和控件继承,可以把下列语句放到main函数里),只设置这些的话窗口无法移动
this->setWindowOpacity(1); //窗口整体透明度,0-1 从全透明到不透明
this->setWindowFlags(Qt::FramelessWindowHint); //设置无边框风格
this->setAttribute(Qt::WA_TranslucentBackground); //设置背景透明,允许鼠标穿透
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btn1_clicked()
{
//切换背景1
ui->centralWidget->setStyleSheet("#centralWidget{background-image: url(:/img/bg.png);}"); //图片放到资源文件里面
}
void MainWindow::on_btn2_clicked()
{
//切换背景2
ui->centralWidget->setStyleSheet("#centralWidget{background-image: url(:/img/bg2.png);}");
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_Drag = true;
m_DragPosition = event->globalPos() - this->pos();
event->accept();
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if (m_Drag && (event->buttons() && Qt::LeftButton))
{
move(event->globalPos() - m_DragPosition);
event->accept();
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
m_Drag=false;
}
main.cpp没有改动,就不贴了。
注意:
1,设置背景图片给centralwidget的stylesheet,而不要设置给mainwindow,否则不显示。
2,qt designer里面拖的控件默认是以UI文件里上层次的控件为父控件,设置父控件的样式会影响子控件的样式,为了不影响,在属性栏设置stylesheet或者代码里设置stylesheet时要加前缀,例如:#myGroupBox{color:red}。注意前缀要和objectName对应。
在代码里设置就是
ui->centralWidget->setStyleSheet("#centralWidget{background-image: url(:/img/bg.png);}");3,以上的移动窗口方法效率不太好,鼠标每次move时都会触发事件,计算位置,移动窗口,重绘窗口,如果不考虑跨平台的话可以用vc的方法。
即:先包含头文件<windows.h>
然后只需要重写mouseMoveEvent一个函数即可。
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (ReleaseCapture())
SendMessage(HWND(this->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
event->ignore();
}