2016-11-29 5 views
1

3,というスケールで水平レイアウトを作成しようとしています。具体的には、これは、私はこれは私が第二の画像がqlabelsのスタイルシートとを変更することで達成され、現時点ではQLabelのフォントサイズを、使用可能なスペースに合わせて動的に変更します。

enter image description here

を目指していますものです

Example

持っているものですスライダ。さらに、グループボックス内のレイアウトに3つのラベルがあるので、グループボックスはその内容に合わせてサイズ変更され、クールです。

ここで、スプリッターを移動するときに、スライダーのアプローチを削除し、代わりにスペースを自動調整したいと考えました。 thisの質問では、OPはresizeEventを再実装しています。これと同じように示唆している他の投稿を見てきました。これはwhile(!doesFit)などと似ています。

このアプローチは、resizeイベントとsplitterMovedイベントの両方で使用してみました。しかし、このアプローチはフィードバックループや他の表示エラーの原因となりがちです。もう1つの質問では、ignoreSizePolicyを有効にしてsizeeventを再トリガするサイズポリシーを防止することをお勧めしますが、レイアウトのサイズ、最小サイズの保持方法、ユーザーが主張する場合はウィジェットを折りたたむ方法が好きです。 HLayoutQLabelsによってトリガーされたサイズ変更イベントを無視しても、まだIMHOの不潔な考えを無視しても問題はないでしょう。

これは、これを達成するための推奨方法であり、あまり不安定ではないソリューションが存在するかどうか、おそらくスタイルシートを使用しているかどうか疑問に思っていました。最小限のサイズ制限(ユーザーが潜在的にグループボックスを非表示にする可能性があるため)もドロップできるいくつかの動作があります。

それが推奨される方法である場合、3つの別々のラベルがあり、そのうちの1つ(番号)がテキストを動的かつ迅速に変更する場合、どのようにフォントメトリックスを使用する必要がありますか?パフォーマンスに影響を与えてはならないし、whileループが私には気になる。

while(!fit)のように聞こえていないようですが、それをカットしようとしています。それとも?重複した質問

Another postに関する

---編集は3ラベルの付いたレイアウトに対処するために作り直した場合にも動作する可能性があるイベントフィルタを作成します。私は最終的にコメントに記載された投稿の変形との最初の投稿のバージョンを使用しました。質問が再開されたら回答を投稿します。

+1

あなたは[こちら](http://stackoverflow.com/questions/2202717/for-qt-4-6-x-how-to-auto-size-text-toからソリューションを試してみました-fit-in-a-specified-width)?このようにwhileループは不要です。 – Dusteh

+1

[QFontMetrics](http://doc.qt.io/qt-4.8/qfontmetrics.html)を使用して、利用可能な幅と高さの両方に合わせてテキストを拡大縮小する係数を計算する必要があります – Dusteh

+0

私はそれが好きですループよりも良い方法です。私はついにIgnoreSizePolicyを追加しなければなりませんでした。私はまだ安定性の考えを心配しています。もしフォントのメトリックが甘くなければ、実行がそこに止まり、resizeEventsを常にトリガすることができますか? – quimnuss

答えて

1

this answerからニュートンの方法アプローチを適用して、与えられたレイアウトのすべてのウィジェットを処理することができます。それはQLabelだけでなく、設定可能なフォントを持つ任意のウィジェットで動作します。

ニュートンのアルゴリズムは、良い出発点が与えられた場合、合理的に迅速に収束します。インタラクティブにサイズ変更するときループを1回だけ実行させるのは非典型的なことではありません。一方、QWidget::sizeHintは整数値であり、ウィジェットは小数点以下のフォントサイズを丸めることがあります。したがって、繰り返しが期待するより少し遅いことがあります。適切なパフォーマンスを確保するために、反復回数に上限があります。

QSizeF sizeHintF()を提供していたラベルのカスタム交換がここでうまくいきます。

ウィジェットの最小サイズは、ウィジェットの内容が変更されたときにサイズが更新されないため、少し伸縮します。しかし、これは簡単に救済することができます。私はより良いKubaOberの答えを考える

// https://github.com/KubaO/stackoverflown/tree/master/questions/label-text-size-vert-40861305 
#include <QtWidgets> 

class LabelStretcher : public QObject { 
    Q_OBJECT 
    static constexpr const char kMinimumsAcquired[] = "ls_minimumsAcquired"; 
    static constexpr const char kStretcherManaged[] = "ls_stretcherManaged"; 
public: 
    LabelStretcher(QObject *parent = 0) : QObject(parent) { 
     apply(qobject_cast<QWidget*>(parent)); 
    } 
    void apply(QWidget *widget) { 
     if (!widget) return; 
     setManaged(widget); 
     setMinimumSize(widget); 
     widget->installEventFilter(this); 
    } 
    void setManaged(QWidget *w, bool managed = true) { 
     w->setProperty(kStretcherManaged, managed); 
    } 
protected: 
    bool eventFilter(QObject * obj, QEvent * ev) override { 
     auto widget = qobject_cast<QWidget*>(obj); 
     if (widget && ev->type() == QEvent::Resize) 
     resized(widget); 
     return false; 
    } 
private: 
    void onLayout(QLayout *layout, const std::function<void(QWidget*)> &onWidget) { 
     if (!layout) return; 
     auto N = layout->count(); 
     for (int i = 0; i < N; ++i) { 
     auto item = layout->itemAt(i); 
     onWidget(item->widget()); 
     onLayout(item->layout(), onWidget); 
     } 
    } 
    void setFont(QLayout *layout, const QFont &font) { 
     onLayout(layout, [&](QWidget *widget){ setFont(widget, font); }); 
    } 
    void setFont(QWidget *widget, const QFont &font) { 
     if (!widget || !widget->property(kStretcherManaged).toBool()) return; 
     widget->setFont(font); 
     setFont(widget->layout(), font); 
    } 
    void setMinimumSize(QWidget *widget) { 
     if (widget->layout()) return; 
     widget->setMinimumSize(widget->minimumSizeHint()); 
    } 
    static int dSize(const QSizeF & inner, const QSizeF & outer) { 
     auto dy = inner.height() - outer.height(); 
     auto dx = inner.width() - outer.width(); 
     return std::max(dx, dy); 
    } 
    qreal f(qreal fontSize, QWidget *widget) { 
     auto font = widget->font(); 
     font.setPointSizeF(fontSize); 
     setFont(widget, font); 
     auto d = dSize(widget->sizeHint(), widget->size()); 
     qDebug() << "f:" << fontSize << "d" << d; 
     return d; 
    } 
    qreal df(qreal fontSize, qreal dStep, QWidget *widget) { 
     fontSize = std::max(dStep + 1.0, fontSize); 
     return (f(fontSize + dStep, widget) - f(fontSize - dStep, widget))/dStep; 
    } 
    void resized(QWidget *widget) { 
     qDebug() << "pre: " << widget->minimumSizeHint() << widget->sizeHint() << widget->size(); 
     if (!widget->property(kMinimumsAcquired).toBool()) { 
     onLayout(widget->layout(), [=](QWidget *widget){ setMinimumSize(widget); }); 
     widget->setProperty(kMinimumsAcquired, true); 
     } 

     // Newton's method 
     auto font = widget->font(); 
     auto fontSize = font.pointSizeF(); 
     qreal dStep = 1.0; 
     int i; 
     for (i = 0; i < 10; ++i) { 
     auto prevFontSize = fontSize; 
     auto d = df(fontSize, dStep, widget); 
     if (d == 0) { 
      dStep *= 2.0; 
      continue; 
     } 
     fontSize -= f(fontSize, widget)/d; 
     fontSize = std::max(dStep + 1.0, fontSize); 
     auto change = fabs(prevFontSize - fontSize)/fontSize; 
     qDebug() << "d:" << d << " delta" << change; 
     if (change < 0.01) break; // we're within 1% of target 
     } 
     font.setPointSizeF(fontSize); 
     setFont(widget, font); 
     qDebug() << "post:" << i << widget->minimumSizeHint() << widget->sizeHint() << widget->size(); 
    } 
}; 
constexpr const char LabelStretcher::kMinimumsAcquired[]; 
constexpr const char LabelStretcher::kStretcherManaged[]; 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    QWidget w; 
    QGridLayout layout{&w}; 
    LabelStretcher stretch{&w}; 
    QLabel labels[6]; 
    QString texts[6] = {"V", "30.0", "kts", "H", "400.0", "ft"}; 
    int i = 0, j = 0, k = 0; 
    for (auto & label : labels) { 
     stretch.setManaged(&label); 
     label.setFrameStyle(QFrame::Box); 
     label.setText(texts[k++]); 
     if (j == 0) label.setAlignment(Qt::AlignRight | Qt::AlignVCenter); 
     else if (j == 1) label.setAlignment(Qt::AlignCenter); 
     layout.addWidget(&label, i, j++); 
     if (j >= 3) { i++; j=0; } 
    } 
    w.show(); 
    return app.exec(); 
} 
#include "main.moc" 
+0

MWEのおかげで、非常に役に立ちました。他の質問と同じように、フォントメトリクスを使用するこのアプローチをなぜ好むでしょうか?ラベルはどこにあるかに関係なく自動的に管理され、おそらくコンピュータよりもスケールファクタが正確なため、アプローチが優れていることがわかります。より多くの議論がありますか? – quimnuss

+0

@quimnuss私はこれがどんな意味でも優れた方法だとは思わない。それは、ニュートンのアルゴリズムを不安定にしない限り、ウィジェットが何であるかには無関係で、動作するようになるアプローチです。ウィジェットのサイズがフォントサイズの変更に伴って増加または減少している場合は、解決策が見つかります。私はバンドの援助としてそれを分類するだろう。本当に堅牢なソリューションのためには、カスタムレイアウトとカスタムウィジェットが必要で、レイアウトとの適切な相互運用が必要です。 –

1

Althoughtは、私はそれがポストに言及した回答のラインでソリューションを望んでいる誰かに役立ちます場合には、これを投稿します。

サンプルテキストは、ラベル、スタイルシートのフォント、およびグループボックスまたはレイアウトのresizeEventに潜在的に配置することができることに注意してください。彼らはスペースのために競争するので、それはラベルのresizeEventで動作しません。

これはKubaOberの回答が優れている理由の1つです。私が考えることができる他の理由は、3つのラベルのスペースがサンプルテキストと異なるので、安定性です。したがって、フォントサイズは正確ではありません。そのため、フォントの変更によってサイズ変更イベントが再度トリガされる可能性があります。

static void fitGroupBoxLabels(QGroupBox* groupbox, const QFont &samplefont, const QLayout* const samplelayout) 
{ 

    groupbox->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); 

    QString sampletext = "V 1000.0 kts"; 
    QRect availablerect = samplelayout->contentsRect(); 

    if(samplefont.pointSizeF() <= 0) return; //not initalized yet, return 
    QRect textrect = QFontMetrics(samplefont).boundingRect(sampletext); 
    if(!textrect.isValid() || !availablerect.isValid()) return; //not initalized yet, return 

    float factorh = availablerect.width()/(float)textrect.width(); 
    float factorw = availablerect.height()/(float)textrect.height(); 
    float factor = std::min(factorh, factorw); 

    if (factor < 0.95 || factor > 1.05) 
    { 
     float fontSize = samplefont.pointSizeF()*factor; 
     QString groupBoxStyle = QString("QGroupBox{font-size:8pt} QLabel{font-size:%1pt}").arg(fontSize); 
     groupbox->setStyleSheet(groupBoxStyle); 
    } 

}

関連する問題