2023-04-23  ShadeWidget

shadewidget の技術的な事2

ShadeWidget を実現する為に必要な技術的な解説

前の説明で 親ウインドウの説明が漏れていたので 書いて置きます。

親ウインドウも背景は透明化

ShadeMain.cpp
ShadeMain::ShadeMain(QWidget* parent) : QDialog(parent) { // 枠なしウインドウ Qt::WindowFlags flags = Qt::Dialog | Qt::WindowStaysOnTopHint; flags |= Qt::FramelessWindowHint; setWindowFlags(flags); // 背景を透明に setAttribute(Qt::WA_TranslucentBackground); setMouseTracking(true);

モードをリサイズ許可の時は 全ボタンを表示し リサイズ不可の時はボタンを見えなくするため 背景は透明化します。
タイトルバーもいりません。

移動を親ウインドウで検知する

タイトルバーの代用品を用意しなければなりません。
マウスでつまんで移動を検知するために MovableButton クラスを作ります。
マウスイベントを検知する機能を追加した QPushButton の派生クラスです。

movablebutton.h
#ifndef MOVABLEBUTTON_H #define MOVABLEBUTTON_H #include <QTextEdit> #include <QPushButton> #include <QObject> class MovableButton : public QPushButton { Q_OBJECT public: MovableButton(QWidget * parent = 0 ); ~MovableButton(){} signals: void mousePressed(QMouseEvent*); void mouseReleased(QMouseEvent*); void mouseMove(QMouseEvent*); public slots: protected: void mousePressEvent(QMouseEvent * event); void mouseReleaseEvent(QMouseEvent * event); void mouseMoveEvent(QMouseEvent * event); private: }; #endif
movablebutton.cpp
#include <QMouseEvent> #include <QDesktopServices> #include <QWidget> #include <QApplication> #include <QDebug> #include "movablebutton.h" MovableButton::MovableButton(QWidget * parent) :QPushButton(parent) { setMouseTracking(true); } void MovableButton::mousePressEvent(QMouseEvent *ev) { if(ev->button() & Qt::LeftButton) emit mousePressed(ev); } void MovableButton::mouseReleaseEvent(QMouseEvent *ev) { if(ev->button() & Qt::LeftButton) emit mouseReleased(ev); } void MovableButton::mouseMoveEvent(QMouseEvent *ev) { emit mouseMove(ev); }

これで準備できました。

親ウインドウの画面部品

shademain.cpp
#include "movablebutton.h" : // 中略 // このソフトのバージョン表示ボタン QHBoxLayout *layout = new QHBoxLayout; layout->setContentsMargins(0,0,0,0); m_btnAbout = new QToolButton(this); m_btnAbout->setFixedWidth(20); m_btnAbout->setFixedHeight(20); m_btnAbout->setObjectName("btnAbout"); m_btnAbout->setCursor(QCursor()); m_btnAbout->setFocusPolicy(Qt::NoFocus); m_btnAbout->setAutoRaise(true); m_btnAbout->setIcon(QIcon(QPixmap(":/icons/shadewidget.png"))); m_btnAbout->setToolTip(QString::fromUtf8(" ShadeWidget について")); connect(m_btnAbout, SIGNAL(clicked()), this, SLOT(about())); layout->addWidget(m_btnAbout); // Qt5.9.5の表示ボタン m_btnAboutQt = new QToolButton(this); m_btnAboutQt->setFixedWidth(20); m_btnAboutQt->setFixedHeight(20); m_btnAboutQt->setObjectName("btnAboutQt"); m_btnAboutQt->setCursor(QCursor()); m_btnAboutQt->setFocusPolicy(Qt::NoFocus); m_btnAboutQt->setAutoRaise(true); m_btnAboutQt->setIcon(QIcon(QPixmap(":/icons/qt-icon.png"))); m_btnAboutQt->setToolTip(QString::fromUtf8(" Qt ライブラリについて")); connect(m_btnAboutQt, SIGNAL(clicked()), qApp, SLOT(aboutQt())); // qApp ここがみそ layout->addWidget(m_btnAboutQt); // これがタイトルバーの代わりのボタン m_btnMovable = new MovableButton(this); m_btnMovable->setFixedHeight(20); connect(m_btnMovable, &MovableButton::mousePressed , this, &ShadeMain::onMousePressed); connect(m_btnMovable, &MovableButton::mouseReleased, this, &ShadeMain::onMouseReleased); connect(m_btnMovable, &MovableButton::mouseMove , this, &ShadeMain::onMouseMove); m_btnMovable->setObjectName("btnMovable"); m_btnMovable->setMinimumWidth(m_wdgtW-240); m_btnMovable->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); m_btnMovable->setToolTip(QString::fromUtf8("ここをドラグするとウインドウを動かせます")); m_btnMovable->setCursor(QCursor()); m_btnMovable->setText(QString::fromUtf8("ShadeWiget")); m_btnMovable->setFocusPolicy(Qt::NoFocus); layout->addWidget(m_btnMovable); // 透明度のスライダー m_opacitySlider = new QSlider(Qt::Horizontal, this); m_opacitySlider->setFixedHeight(20); m_opacitySlider->setMinimumWidth(100); m_opacitySlider->setToolTip(QString::fromUtf8("透明度¥nスライダーを動かして調整")); m_opacitySlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); m_opacitySlider->setMaximum(90); m_opacitySlider->setMinimum(30); m_opacitySlider->setFocusPolicy(Qt::NoFocus); int opaval = (int)(cfg->m_opacity*100.0F); m_opacitySlider->setValue(opaval); SetOpacity(opaval); // 直接は接続しない connect(m_opacitySlider, &QSlider::valueChanged, this, &ShadeMain::SetOpacity); layout->addWidget(m_opacitySlider); // スペーサーが必要 QSpacerItem* spacer = new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); layout->addItem(spacer); // モード変更ボタン m_btnModeChange = new QToolButton(this); m_btnModeChange->setFixedWidth(20); m_btnModeChange->setFixedHeight(20); m_btnModeChange->setObjectName("btnModeChange"); m_btnModeChange->setCursor(QCursor()); m_btnModeChange->setFocusPolicy(Qt::NoFocus); m_btnModeChange->setAutoRaise(true); // m_btnModeChange->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(m_btnModeChange, &QAbstractButton::clicked, this, &ShadeMain::onModeChange); layout->addWidget(m_btnModeChange); // 終了ボタン QToolButton* closebtn = new QToolButton(this); closebtn->setObjectName("closebtn"); closebtn->setFixedWidth(20); closebtn->setFixedHeight(20); closebtn->setCursor(QCursor()); closebtn->setFocusPolicy(Qt::NoFocus); closebtn->setAutoRaise(true); closebtn->setIcon(QIcon(QPixmap(":/icons/monoclose.png"))); closebtn->setToolTip(QString::fromUtf8("閉じる")); // closebtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(closebtn, &QAbstractButton::clicked, this, &ShadeMain::close); layout->addWidget(closebtn);

モード変更した時に setVisible(false)で見えなくするボタンがあるので スペーサーが無いと 右寄せにならないので注意が必要です。
この時の Expand 属性に工夫をしないと上手く動きませんでした。

次にマウスで移動した時の処理が必要です。

shademain.cpp
: // 中略 void ShadeMain::onMousePressed(QMouseEvent* event) { //save the press position (this is relative to the current widget) m_pressPos = event->pos(); // qDebug() << __func__ << m_widgetname << m_pressPos; isMoving = true; } // タイトルバー移動で ShadeWidgetも移動 void ShadeMain::onMouseMove(QMouseEvent* event) { if(isMoving){ QPoint diff = event->pos() - m_pressPos; QPoint parentpos = this->pos(); QPoint newpos = parentpos + diff; move(newpos); m_wdgtX = newpos.x(); m_wdgtY = newpos.y(); // qDebug() << "newpos=" << newpos; if(m_shadewdgt){ QPoint winpos = m_shadewdgt->pos() + diff; // qDebug() << "winpos=" << winpos; m_shadewdgt->move(winpos); } m_parentpos = newpos; } } void ShadeMain::onMouseReleased(QMouseEvent*) { // qDebug() << __func__ << m_widgetname << window()->pos() << m_pressPos; isMoving = false; }

サンプルソースダウンロード

説明不足なので プログラムソースを残します。

shadewidget サンプルソース 
ダウンロード 

最終更新日 2023-05-13
この記事を共有しませんか?
ブックマーク