この記事はTakumi Akashiro ひとり Advent Calendar 2020の3日目になります。
前置きの前置き
はい、Advent Calendarの3日目にして、もうネタが無くなりました。
最初の方にはちょっと実用的な記事を書く意識1がありましたが
仕方ないので、ここから来週の月曜までは好き勝手調べた内容を書いてきます。
TAとかまったく関係ないです。
というわけで、3日目の記事、どうぞ!
前置き
皆さんはウィンドウの透過処理、使ったことありますか?自分は今までの仕事では一回も無いですね!
突然、ウィンドウにオーバーレイさせるアプリケーションとか作りたくなったので、ちょっと覚えていこうと思います(投げやり)
ウィンドウを半透過するには得手不得手があり、使い分けが必要だったので、
今日の記事はその辺を踏まえながら解説していきたいと思います!
本日のサンプルコード
#!python3
# encoding:utf-8
from PySide2 import QtWidgets
from PySide2 import QtCore
class Window(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowTitle("Sample")
self.setStyleSheet("background-color:white;")
self.setFixedSize(480, 320)
hbox = QtWidgets.QHBoxLayout()
vbox = QtWidgets.QVBoxLayout()
hbox.addLayout(vbox)
button_first = QtWidgets.QPushButton("Button: 1")
button_first.setStyleSheet("background-color:gray; color:white;height:100%")
vbox.addWidget(button_first)
button_second = QtWidgets.QPushButton("Button: 2")
button_second.setStyleSheet("background-color:darkgray; color:white;height:100%")
vbox.addWidget(button_second)
textedit = QtWidgets.QTextEdit("QtWidgets.QTextEdit")
textedit.setStyleSheet("background-color:lightgray;")
hbox.addWidget(textedit)
self.setLayout(hbox)
if __name__ == "__main__":
app = QtWidgets.QApplication()
window = Window()
window.show()
exit(app.exec_())
はい、Qt製の何の変哲もない雑なウィンドウですね。
本日はこれを透過させてみたいと思います。
手法1 ウィンドウ背景の透明化オプションをセットする
self.setWindowFlagsに「WA_TranslucentBackground」をセットすることで1ウィンドウの背景が透過するようになります。
ただしそのままでは、「WA_TranslucentBackground」をセットした時に
追加される背景を描画しない「WA_NoSystemBackground」の影響で背景色が描画されないので、
paintEvent側で背景色を描画する必要があります。
class Window(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
# ~中略~
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setStyleSheet("background-color: rgba(255, 255, 255, 127);")
def paintEvent(self, event):
# NOTE: トップレベルのWidgetはWA_TranslucentBackgroundフラグが立つと、
# 背景が描画されなくなるので、paintEvent側で描画する。
painter = QtGui.QPainter(self)
painter.fillRect(0, 0, self.width(), self.height(), painter.background())
メリット | 特定Widgetのみを透過できる |
デメリット | ウィンドウのWidgetの透過には WindowFlagsのFramelessWindowHintが必要なため、 タイトルバーが消えてしまう |
手法2 ウィンドウに直接透明度を適用する
class Window(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
# ~中略~
self.setWindowOpacity(0.5)
メリット | めちゃくちゃ簡単に透過を実装できる |
デメリット | Widget個別に透過度を設定できない |
締め
評価ラベル | ランク(5段階) |
---|---|
おすすめ度 | ★ |
難易度 | ★ |
ニッチ | ★★★★ |
汎用性 | ★ |
もやもや度 | ★★★★ |
(上記は加工した画像です)
今回、実はオーバーレイの件とは別件でこういう感じをやりたくて、調べていたんですがダメでした……
一応PySide2+Qtをビルドしなおして、QtWinモジュールを追加すれば、Win7時代によくあったガラスフレームが使えるようで、
上記の画像っぽい感じになるんですが…今回はそこまでの情熱はないです……
まあ手法1に自作のタイトルバーを追加すればいいだけなんで、問題はないんですけどね!!!!(精一杯の負け惜しみ)
というわけで個人的には若干消化不良な結果になりましたが、
今日の記事はここまでで終わりです。
ではでは!