web-dev-qa-db-ja.com

Qtでウィジェットのアスペクト比を維持する方法は?

Qtでウィジェットのアスペクト比を維持するにはどうすればよいですか?ウィジェットを中央に配置するのはどうですか?

32
Bleadof

独自のレイアウトマネージャーを実装する必要はありません。 QWidgetを継承して再実装すると、

_int QWidget::heightForWidth( int w ) { return w; }
_

正方形を保つために。ただし、heightForWidth()はX11のトップレベルウィンドウでは機能しません。X11プロトコルではサポートされていないためです。中央揃えについては、QBoxLayout::addWidget()の3番目のパラメーターまたはQGridLayout::addWidget()の5番目のパラメーターとして_Qt::AlignCenter_を渡すことができます。

注:少なくとも新しいバージョンのQtでは、QWidgetにはheightForWidthまたはwidthForHeightがありません(したがって、オーバーライドできません)。したがって、setWidthForHeight(true)またはsetHeightForWidth(true)QGraphicsLayoutの子孫に対してのみ効果があります

17

正解は、カスタムレイアウトマネージャーを作成することです。 QLayout をサブクラス化することで可能になります。

QLayoutをサブクラス化するときに実装するメソッド

void addItem(QLayoutItem * item);
アイテムをレイアウトに追加します。
int count()const;
アイテム数を返します。
QLayoutItem * itemAt(int index)const;
インデックスのアイテム参照を返すか、存在しない場合は0を返します。
QLayoutItem * takeAt(int index);
インデックスからレイアウトからアイテムを取得して返します。存在しない場合は0を返します。
Qt :: Orientations expandedDirections()const;
レイアウトを展開する方向を返します。
bool hasHeightForWidth()const;
レイアウトが幅の計算で高さを処理するかどうかを判断します。
QSize minimumSize()const;
レイアウトの最小サイズを返します。
void setGeometry(const QRect&rect);
レイアウトのジオメトリとその中のアイテムを設定します。ここでは、アスペクト比を維持し、センタリングを行う必要があります。
QSize sizeHint()const;
レイアウトの適切なサイズを返します。

参考文献

8
Bleadof

resize()内からresizeEvent()を呼び出すことは、私にとってはうまくいきませんでした-せいぜい、無限ループで、ウィンドウが2回リサイズされると、ちらつきが発生します。

アスペクト比を一定に保つ「正しい」方法は、カスタムレイアウトを作成することだと思います。 QLayoutItem::hasHeightForWidth()QLayoutItem::heightForWidth()の2つのメソッドのみをオーバーライドする必要があります。

5
dF.

私の場合、heightForWidth()のオーバーライドは機能しません。そして、誰かにとっては、サイズ変更イベントを使用する実際の例を取得することが役立つかもしれません。

最初にqObjectをサブクラス化してフィルターを作成します。 イベントフィルターの詳細

class FilterObject:public QObject{
public:
    QWidget *target = nullptr;//it holds a pointer to target object
    int goalHeight=0;
    FilterObject(QObject *parent=nullptr):QObject(parent){}//uses QObject constructor
    bool eventFilter(QObject *watched, QEvent *event) override;//and overrides eventFilter function
};

次に、eventFilter関数。警告を防ぐために、そのコードはFilterObject定義の外部で定義する必要があります。 この回答に感謝します。

bool FilterObject::eventFilter(QObject *watched, QEvent *event) {
    if(watched!=target){//checks for correct target object.
        return false;
    }
    if(event->type()!=QEvent::Resize){//and correct event
        return false;
    }

    QResizeEvent *resEvent = static_cast<QResizeEvent*>(event);//then sets correct event type

    goalHeight = 7*resEvent->size().width()/16;//calculates height, 7/16 of width in my case
    if(target->height()!=goalHeight){
        target->setFixedHeight(goalHeight);
    }

    return true;
};

次に、メインコードでFilterObjectを作成し、それをEventFilterリスナーとしてターゲットオブジェクトに設定します。 この回答に感謝します。

FilterObject *filter = new FilterObject();
QWidget *targetWidget = new QWidget();//let it be target object
filter->target=targetWidget;
targetWidget->installEventFilter(filter);

これで、フィルターはすべてのtargetWidgetのイベントを受け取り、サイズ変更イベントで正しい高さを設定します。

1
PolyGlot