翻譯|使用教程|編輯:龔雪|2024-10-22 11:35:28.610|閱讀 157 次
概述:本文主要介紹如何在Qt應用程序中實現一個半透明的背景,歡迎下載最新版組件體驗~
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
相關鏈接:
Qt 是目前最先進、最完整的跨平臺C++開發工具。它不僅完全實現了一次編寫,所有平臺無差別運行,更提供了幾乎所有開發過程中需要用到的工具。如今,Qt已被運用于超過70個行業、數千家企業,支持數百萬設備及應用。
本文將為大家展示如何制作一個帶有半透明背景的圓形窗口。
將背景設置為半透明的小部件將對所有未繪制的像素透明,并且背景將通過不透明度低于100%繪制的像素發光,沒有繪制的像素也不會接收任何鼠標輸入,這可用于自定義頂級小部件的形狀。在大多數窗口系統中,設置某些窗口標志將導致窗口裝飾(標題欄、窗口框架、按鈕)被禁用,從而允許創建特殊形狀的窗口。在這個示例中,我們使用這個特性來創建一個包含模擬時鐘的圓形窗口。
由于這個示例的窗口沒有提供File菜單或關閉按鈕,因此我們提供了一個帶有Exit條目的上下文菜單,以便可以關閉該示例,單擊窗口上方的鼠標右鍵來打開此菜單。
Qt技術交流群:166830288 歡迎一起進群討論
ShapedClock類基于AnalogClock示例中定義的AnalogClock類,整個類定義如下:
class ShapedClock : public QWidget { Q_OBJECT public: ShapedClock(QWidget *parent = nullptr); QSize sizeHint() const override; protected: void mouseMoveEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void paintEvent(QPaintEvent *event) override; private: QPoint dragPosition; };
()現在半透明背景(時鐘面)上繪制模擬時鐘,此外我們實現了sizeHint(),這樣就不必顯示地調整小部件的大小。
由于包含時鐘小部件的窗口將沒有標題欄,因此我們提供了()和()的實現,來允許在屏幕上拖動時鐘,dragPosition變量使我們能夠跟蹤用戶最后單擊小部件的位置。
ShapedClock構造函數設置一個計時器,并將其連接到小部件的update()槽。此外,我們向小部件添加了一個操作,當右鍵單擊小部件時,該操作將通過上下文菜單自動變為可用。
ShapedClock::ShapedClock(QWidget *parent) : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint) { setAttribute(Qt::WA_TranslucentBackground); QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, QOverload<>::of(&ShapedClock::update)); timer->start(1000); QAction *quitAction = new QAction(tr("E&xit"), this); quitAction->setShortcut(tr("Ctrl+Q")); connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit); addAction(quitAction); setContextMenuPolicy(Qt::ActionsContextMenu); setToolTip(tr("Drag the clock with the left mouse button.\n" "Use the right mouse button to open a context menu.")); setWindowTitle(tr("Shaped Analog Clock")); }
我們通過設置 小部件屬性來請求透明窗口,通過在窗口管理器上設置 標志來通知窗口管理器該窗口不使用窗口框架來裝飾。因此,我們需要為用戶提供一種在屏幕上移動時鐘的方法。
鼠標按鈕事件被傳遞給mousePressEvent()處理程序:
void ShapedClock::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { dragPosition = event->globalPosition().toPoint() - frameGeometry().topLeft(); event->accept(); } }
如果在小部件上按下鼠標左鍵,我們將以全局(屏幕)坐標記錄小部件框架的左上角位置(即使隱藏時)與鼠標單擊發生點之間的位移。如果用戶按住左鍵移動鼠標,將使用此位移。由于我們對事件進行了操作,因此通過調用它的()函數來接受它。
如果鼠標移動到小部件上,則調用mouseMoveEvent()處理程序。
void ShapedClock::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { move(event->globalPosition().toPoint() - dragPosition); event->accept(); } }
如果在移動鼠標時按住左鍵,則小部件的左上角將移動到通過從全局坐標中的當前光標位置減去dragPosition給出的位置。如果我們拖動小部件,也接受事件。
paintEvent()函數主要與模擬時鐘示例中描述的相同,另外我們使用QPainter::drawEllipse()來繪制一個圓形的鐘面,將畫筆的不透明度降低到90%,并使用調色板的默認背景色。
void ShapedClock::paintEvent(QPaintEvent *) { static const QPoint hourHand[4] = { QPoint(5, 14), QPoint(-5, 14), QPoint(-4, -71), QPoint(4, -71) }; static const QPoint minuteHand[4] = { QPoint(4, 14), QPoint(-4, 14), QPoint(-3, -89), QPoint(3, -89) }; static const QPoint secondsHand[4] = { QPoint(1, 14), QPoint(-1, 14), QPoint(-1, -89), QPoint(1, -89) }; const QColor hourColor(palette().color(QPalette::Text)); const QColor minuteColor(palette().color(QPalette::Text)); const QColor secondsColor(palette().color(QPalette::Accent)); int side = qMin(width(), height()); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.translate(width() / 2, height() / 2); painter.scale(side / 200.0, side / 200.0); painter.setPen(Qt::NoPen); painter.setBrush(palette().window()); painter.setOpacity(0.9); painter.drawEllipse(QPoint(0, 0), 98, 98); painter.setOpacity(1.0); QTime time = QTime::currentTime(); painter.setPen(Qt::NoPen); painter.setBrush(hourColor); painter.save(); painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0))); painter.drawConvexPolygon(hourHand, 4); painter.restore(); for (int i = 0; i < 12; ++i) { painter.drawRect(73, -3, 16, 6); painter.rotate(30.0); } painter.setBrush(minuteColor); painter.save(); painter.rotate(6.0 * time.minute()); painter.drawConvexPolygon(minuteHand, 4); painter.restore(); painter.setBrush(secondsColor); painter.save(); painter.rotate(6.0 * time.second()); painter.drawConvexPolygon(secondsHand, 4); painter.drawEllipse(-3, -3, 6, 6); painter.drawEllipse(-5, -68, 10, 10); painter.restore(); painter.setPen(minuteColor); for (int j = 0; j < 60; ++j) { painter.drawLine(92, 0, 96, 0); painter.rotate(6.0); } }
最后為小部件實現sizeHint(),以便在它第一次顯示時給出一個合理的默認大小:
QSize ShapedClock::sizeHint() const { return QSize(200, 200); }
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:慧都網