Help us understand the problem. What is going on with this article?

[maya, motionbuilder, nuke, etc] Qt アプリでパネルをドラッグ中に意図せずドッキングされないようにする方法

※記事に関しましてご注意下さい
こちらでは「対処法そのもの」よりも「そもそも何故その問題がおこるのか」を探るべく調査した内容になります。
実際の現場では具体的な解決策として様々な手段がとられますが、その根源は実は同じであることも多く、
仕組みを知ることで利点・欠点をつかみ、未来に起こるトラブルを防ぐ・拡張した使用方法に発展させるなどを考えています。
あくまでも個人調査のメモです。間違い・勘違いが含まれている可能性もありますので予めご了承ください。

調査のきっかけ

元々は、

motionbuilder で追加したウィンドウ・掴んだウィンドウが
色んなパネルの合間に勝手にドッキングして配置されるのを防ぎたい、
かつ、できればドッキングするかしないかを選択したい(ドッキングしたい場合もある)

という相談から調査を始めました。
※ motionbuilder 限定であれば .ini でドッキングを全オフにすることは可能です

これについてはネット上には多くの意見・案・スクリプトがあり、その多くがアプリケーション内の PyQt/PySide ウィンドウの設定を変更してドッキングできなくする、というものです。
ですが ドッキングさせたい場面もあるはず で、その場合との共存の面で今一しっくりくるものがなく調査しました。

調べた結果

ウィンドウ・パネルを移動する際に「Ctrl を押しながら」を移動するとドッキングせず、
通常通り移動するとドッキングモードが復活します。

以上です。至ってシンプル。設定変更もスクリプトも必要なし。

実際に maya, motionbuilder, nuke, python + pyside などでその挙動を確認済みです。
※ 3dsmax も qt 挙動合わせなのか同様の挙動でした。

何故その動作になるのか

今は多くのアプリケーションがパネルの表示の仕組みとして Qt を採用しています。
maya, motionbuilder, nuke などなど PyQt/PySide ベースのアプリもそれにあたります。
そして、PyQt/PySide も Qt も広く普及し、大分古くから利用されている仕組みです。

それなら、、、

元々そういう動作を準備しているのでは・・・

と考えました。

Qt 内部コードは以下で参照できますが、
https://code.qt.io/cgit/
そこから QDockWidget に関しての部分を調べると以下になります。

https://code.qt.io/cgit/qt/qtbase.git/tree/src/widgets/widgets/qdockwidget.cpp

この中で state->ctrlDrag で分岐処理している箇所を辿ると、
Ctrl キーを押した状態の場合には通常のウィンドウ移動の動作になる
という記述になっています。

なんと、準備されていました。。。

Python のサンプルコード

アプリケーション内の動作はスクリプト無しで確認できます。

もし自分で作成したウィンドウ内で Ctrl キーの組み合わせの違いを確認したい場合、例えば以下のコードで確認できます。

※from, import の仕方や変数名等はここでは重要でないためテキトウに書いています。

dockTest.py
# -*- coding: utf-8 -*-
try:
    from PySide2 import QtCore, QtWidgets
except:
    from PySide import QtCore, QtGui as QtWidgets

if __name__ == '__main__':
    app = QtWidgets.QApplication.instance()

    standalone = app is None
    if standalone:
        import sys
        app = QtWidgets.QApplication(sys.argv)

    msg = u'''
    左のパネルをドラッグし移動して下さい。
    (Ctrl を押しながらの場合はドッキングされません)
    '''

    win = QtWidgets.QMainWindow()
    win.setWindowTitle(u'Dock demo')
    win._w1 = QtWidgets.QPlainTextEdit(msg, win)
    win._w2 = QtWidgets.QDockWidget(u'QDockWidget', win)
    win.setCentralWidget(win._w1)
    win.addDockWidget(QtCore.Qt.LeftDockWidgetArea, win._w2)
    win.show()

    if standalone:
        sys.exit(app.exec_())
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away