半透明の背景
この例では、半透明の背景を持つ丸いウィンドウを作成する方法を示しています。

背景を半透明に設定したウィジェットは、描画されていないピクセルすべてが透明になり、不透明度が100%未満で描画されたピクセルからは背景が透けて見えます。まったく描画されていないピクセルには、マウス入力も受け付けられません。この機能を利用して、最上位ウィジェットの形状をカスタマイズすることができます。 ほとんどのウィンドウシステムでは、特定のウィンドウフラグを設定することで、ウィンドウ装飾(タイトルバー、ウィンドウフレーム、ボタン)を無効にでき、特殊な形状のウィンドウを作成することが可能です。この例では、この機能を利用して、アナログ時計を表示する円形のウィンドウを作成します。
この例のウィンドウには「File 」メニューや閉じるボタンがないため、例を閉じられるように「Exit 」という項目を含むコンテキストメニューを用意しています。ウィンドウ上でマウスの右ボタンをクリックすると、このメニューが開きます。
ShapedClock クラスの定義
ShapedClock クラスは、「アナログ時計」の例で定義された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;
};paintEvent() の実装では、半透明の背景(文字盤)上にアナログ時計を描画します。さらに、ウィジェットのサイズを明示的に変更する必要がないように、sizeHint() も実装しています。
時計ウィジェットを含むウィンドウにはタイトルバーがないため、mouseMoveEvent() およびmousePressEvent() の実装を用意し、画面上で時計をドラッグできるようにしています。dragPosition 変数を使用することで、ユーザーがウィジェット上で最後にクリックした位置を追跡できます。
ShapedClockクラスの実装
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"));
}Qt::WA_TranslucentBackground ウィジェット属性を設定することで、透明なウィンドウを要求します。また、ウィジェットにQt::FramelessWindowHint フラグを設定することで、ウィンドウマネージャーに対し、このウィジェットにウィンドウフレームを表示しないよう指示します。その結果、ユーザーが画面上で時計を移動できる手段を用意する必要があります。
マウスボタンイベントは、mousePressEvent() ハンドラに送信されます:
void ShapedClock::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
dragPosition = event->globalPosition().toPoint() - frameGeometry().topLeft();
event->accept();
}
}ウィジェット上でマウスの左ボタンが押された場合、ウィジェットのフレームの左上位置(非表示の場合でも)とマウスクリックが発生した地点との間の、グローバル(画面)座標での変位を記録します。この変位は、ユーザーが左ボタンを押したままマウスを移動させた際に使用されます。 イベントに対して処理を行ったため、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);
{
QPainterStateGuard guard(&painter);
painter.rotate(30.0 * ((time.hour() + time.minute() / 60.0)));
painter.drawConvexPolygon(hourHand, 4);
}
for (int i = 0; i < 12; ++i) {
painter.drawRect(73, -3, 16, 6);
painter.rotate(30.0);
}
painter.setBrush(minuteColor);
{
QPainterStateGuard guard(&painter);
painter.rotate(6.0 * time.minute());
painter.drawConvexPolygon(minuteHand, 4);
}
painter.setBrush(secondsColor);
{
QPainterStateGuard guard(&painter);
painter.rotate(6.0 * time.second());
painter.drawConvexPolygon(secondsHand, 4);
painter.drawEllipse(-3, -3, 6, 6);
painter.drawEllipse(-5, -68, 10, 10);
}
painter.setPen(minuteColor);
for (int j = 0; j < 60; ++j) {
painter.drawLine(92, 0, 96, 0);
painter.rotate(6.0);
}
}最後に、ウィジェットが最初に表示された際に適切なデフォルトサイズが設定されるよう、sizeHint() を実装します:
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.