專案結構
shapewidget.h:自訂 Widget 類別宣告
shapewidget.cpp:事件處理與繪圖實作
main.cpp:程式進入點
shapewidget.h
#ifndef SHAPEWIDGET_H
#define SHAPEWIDGET_H
#include <QtGui>
class QPoint;
class ShapeWidget : public QWidget {
Q_OBJECT
public:
ShapeWidget(QWidget *parent = 0);
protected:
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void paintEvent(QPaintEvent *);
private:
QPoint dragPosition;
};
#endif
shapewidget.cpp 關鍵實作
ShapeWidget::ShapeWidget(QWidget *parent)
: QWidget(parent, Qt::FramelessWindowHint) // 無邊框視窗提示
{
QPixmap pix;
pix.load(":/images/Watermelon.png", 0,
Qt::AvoidDither | Qt::ThresholdDither | Qt::ThresholdAlphaDither);
resize(pix.size()); // 視窗大小 = 圖片大小
setMask(pix.mask()); // 以圖片透明區域建立非矩形遮罩
}
void ShapeWidget::mousePressEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
dragPosition = event->globalPos() - frameGeometry().topLeft();
event->accept();
}
if (event->button() == Qt::RightButton) close();
}
void ShapeWidget::mouseMoveEvent(QMouseEvent *event) {
if (event->buttons() & Qt::LeftButton) {
move(event->globalPos() - dragPosition);
event->accept();
}
}
void ShapeWidget::paintEvent(QPaintEvent *) {
QPainter painter(this);
painter.drawPixmap(0, 0, QPixmap(":/images/Watermelon.png"));
// 若改為 QPixmap() 則僅繪製框架,不顯示圖片內容
}
main.cpp
#include <QApplication>
#include "shapewidget.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
ShapeWidget shape;
shape.show();
return app.exec();
}
核心技術點總結
| 技術 | API / 方法 | 作用 |
| 無邊框視窗 | Qt::FramelessWindowHint | 移除標題列、邊框、系統選單 |
| 非矩形視窗 | setMask(QRegion) | 以圖片 Alpha 通道建立點擊穿透遮罩 |
| 滑鼠拖曳移動 | globalPos() - frameGeometry().topLeft() | 計算拖曳位移,move() 更新視窗位置 |
| 自訂繪圖 | paintEvent + QPainter::drawPixmap | 每次重繪繪製背景圖片 |
| 資源系統 | :/images/Watermelon.png | 透過 .qrc 編譯進二進位,免外部檔案 |
應用場景
- 不規則造型視窗(音樂播放器皮膚、啟動畫面、桌面小工具)。
- 全螢幕獨特 UI、遊戲啟動器、自訂對話框。