1. 程式人生 > >Qt開發:無邊框異形視窗,透明背景,可移動

Qt開發:無邊框異形視窗,透明背景,可移動

很多端遊的啟動器客戶端都是異形視窗,無邊框,自繪並重寫了最小化、最大化、關閉按鈕。本文具體講一下實現。

步驟:

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();  
}  
最後要說的是,本例並未實現視窗的縮放,無邊框縮放是一個很複雜的問題,後面再說。