1. ホーム
  2. python

[解決済み] QSizePolicy.MinimumとQSizePolicy.Preferredはどう違うのですか?

2022-02-16 07:42:59

質問

preferred policyは非常に柔軟なポリシーであり、ウィジェットのサイズはsizeHint()よりも小さくも大きくもできると書いてありました。
しかし、ウィンドウのサイズを大きくしたり小さくしたりしているうちに、両者の違いがわからなくなってしまいました。

< QSizePolicy.Minimum >

from PySide2 import QtWidgets

app = QtWidgets.QApplication([])

window = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
vMinimumButton = QtWidgets.QPushButton("h_Minimum, v_Fixed")
hMinimumButton = QtWidgets.QPushButton("h_Fixed, v_Minimum")
bMinimumButton = QtWidgets.QPushButton("h_Minimum, v_Minimum")

vMinimumButton.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
hMinimumButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
bMinimumButton.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)

layout.addWidget(vMinimumButton)
layout.addWidget(hMinimumButton)
layout.addWidget(bMinimumButton)
window.setLayout(layout)
window.show()

app.exec_()

< QSizePolicy.Preferred >

from PySide2 import QtWidgets

app = QtWidgets.QApplication([])

window = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
vPreferredButton = QtWidgets.QPushButton("h_Preferred, v_Fixed")
hPreferredButton = QtWidgets.QPushButton("h_Fixed, v_Preferred")
bPreferredButton = QtWidgets.QPushButton("h_Preferred, v_Preferred")

vPreferredButton.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
hPreferredButton.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
bPreferredButton.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)

layout.addWidget(vPreferredButton)
layout.addWidget(hPreferredButton)
layout.addWidget(bPreferredButton)
window.setLayout(layout)
window.show()

app.exec_()

解決方法は?

私は、簡潔ではあるが、完全な paxdiabloの回答 .

まず、Qt のサイズポリシーの名前は、一見すると直感に反しています。
それを理解するには、ドキュメントを注意深く根気よく理解し、場合によってはテストすることが必要です。一旦その要点をつかめば、おそらくその命名の背後にある論理と仮定に気づき、実際に意味をなすようになるでしょう( 直感的でない は、必ずしも いけない 複雑なテーマでは、直感だけで間違った選択をしないように、より意識する必要があります)。

理解すべき重要なことは、これらは常に サイズヒント のウィジェットで、そのヒントが参照としてどのように使われるかを示しています。

Maximum は、そのヒントが 最大 ウィジェットのサイズ: このサイズより大きくすることはできません。
Minimum というのは、ヒントが 最小 のサイズであり、これより小さくすることはできません。
次のことを忘れないでください。 minimum*maximum* (とともに * 存在 Size , Width または Height ) がこれらのアスペクトをオーバーライドします。 Expanding は、ヒントが望ましいサイズであることを意味し、もしスペースが残っていれば、そのウィジェットはそれを使おうとします。

次に、QWidgetにも minimumSizeHint は、推奨される最小サイズです:有効なサイズを返せば、それは ない より小さくなります (これも、最小サイズが明示的に指定されていない限り)。

また、いくつかのウィジェットには独特の動作があり、コードに違いが見られない理由もこれだと理解する必要があります。たとえば、QPushButton は、次のような結果を返します。 sizeHint() の場合でも minimumSizeHint() の場合、それはその内容に基づいており、その デフォルトでは、Qtのボタンは高さが固定されています。

いつものように、動作を理解するためには実験することが最適です。
基本的なQWidgetをベースにすることで、Widget固有のヒントやポリシーに起因する予期せぬ動作を回避できます。

コンテキスト メニューを使用してポリシーを設定し、最終的に結果を確認するためにウィンドウをリサイズすることができます。表示される値は、現在のポリシーとサイズヒントを示しています。

from PySide2 import QtCore, QtGui, QtWidgets

policyNames = 'Fixed', 'Minimum', 'Maximum', 'Preferred', 'Expanding'
policyNameDict = {}
policyValueDict = {}
for name in policyNames:
    policy = getattr(QtWidgets.QSizePolicy, name)
    policyNameDict[policy] = name
    policyValueDict[name] = policy

class TestWidget(QtWidgets.QWidget):
    def sizeHint(self):
        return QtCore.QSize(150, 30)

    def minimumSizeHint(self):
        return QtCore.QSize(10, 10)

    def contextMenuEvent(self, event):
        currentPolicy = self.sizePolicy()
        menu = QtWidgets.QMenu()
        group = QtWidgets.QActionGroup(menu, exclusive=True)
        for name in policyNames:
            action = group.addAction(name)
            action.setCheckable(True)
            policy = policyValueDict[name]
            action.setData(policy)
            if policy == currentPolicy.horizontalPolicy():
                action.setChecked(True)
        menu.addActions(group.actions())
        res = menu.exec_(event.globalPos())
        if res:
            # PySide requires reconversion of the data, on PyQt the
            # res.data() alone is enough;
            currentPolicy.setHorizontalPolicy(
                QtWidgets.QSizePolicy.Policy(res.data()))
            self.setSizePolicy(currentPolicy)
            self.update()

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.drawRect(self.rect().adjusted(0, 0, -1, -1))
        text = '{policy}\n{width}x{height}'.format(
            policy=policyNameDict[self.sizePolicy().horizontalPolicy()], 
            width=self.sizeHint().width(), 
            height=self.sizeHint().height(), 
        )
        qp.drawText(self.rect(), QtCore.Qt.AlignCenter, text)


app = QtWidgets.QApplication([])

window = QtWidgets.QWidget()
layout = QtWidgets.QHBoxLayout(window)
for i in range(3):
    layout.addWidget(TestWidget())
window.show()

app.exec_()