2010-07-21 6 views
1

У меня есть QGraphicsTextItem объектов на QGraphicsScene. Пользователь может масштабировать объекты QGraphicsTextItem, перетаскивая углы. (Для этого я использую специальный «редактор преобразований».) Пользователь также может изменить размер QGraphicsTextItem, изменив размер шрифта с панели свойств. То, что я хотел бы сделать, это унифицировать их так, что когда пользователь масштабирует объект, перетаскивая угол с помощью мыши, за кулисами он фактически вычисляет «Какой размер шрифта необходим, чтобы результирующий объект соответствовал целевому размеру и сохранял масштабный коэффициент при 1,0? "Рассчитать размер шрифта QGraphicsTextItem на основе шкалы

Что я делаю сейчас выпускающая масштаб объекта в обычном режиме с использованием QGraphicsItem::mouseMoveEvent, а затем вызвав метод FinalizeMapScale в QGraphicsItem::mouseReleaseEvent когда масштаб мыши завершен. Затем этот метод должен изменить шрифт на соответствующий размер и установить масштаб на 1,0.

У меня есть решение, которое работает, но я не сумасшедший. Я относительно новичок в Qt и C++, поэтому буду благодарен за любые комментарии или исправления.

  • Есть ли лучший способ архитектовать все это?
  • Есть ли методы Qt, которые уже делают это?
  • Является ли мой метод на правильном пути, но имеет некоторые ошибки Qt или C++?

Не стесняйтесь прокомментировать мой ответ ниже, представив свое собственное предпочтительное решение. Благодаря!

[EDIT] В соответствии с запросом в комментарии, здесь приведены основы масштабирующего кода. Мы фактически пошли в другом направлении, так что этот код (и код ниже) больше не используется. Этот код находится в методе mouseMoveEvent, предварительно установив флаг «scaling_» в значение true в mousePressEvent, если щелкнуть мышью в нижней правой «горячей точке». Обратите внимание, что этот код находится в декораторе QGraphicsItem, который содержит указатель на целевое масштабирование. Эта абстракция была необходима для нашего проекта, но, вероятно, это слишком много для большинства целей. не

void TransformDecorator::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { 
    ... 
    if (scaling_) { 
    QGraphicsItem *target_item = target_->AsQGraphicsItem(); 
    target_item->setTransformOriginPoint(0.0, 0.0); 
    QPointF origin_scene = mapToScene(target_item->transformOriginPoint()); 
    QPointF scale_position_scene = mapToScene(event->pos()); 
    qreal unscaled_width = target_item->boundingRect().width(); 
    qreal scale_x = (scale_position_scene.x() - origin_scene.x())/unscaled_width; 
    if (scale_x * unscaled_width < kMinimumSize) { 
     scale_x = kMinimumSize/unscaled_width; 
    } 
    target_item->setScale(scale_x); 
    } else { 
    QGraphicsObject::mouseMoveEvent(event); 
    } 
} 

ответ

1

Пожалуйста, не священные войны о конструкции петли с-выходом. Нам это удобно.

void MapTextElement::FinalizeMapScale() { 

    // scene_document_width is the width of the text document as it appears in 
    // the scene after scaling. After we are finished with this method, we want 
    // the document to be as close as possible to this width with a scale of 1.0. 
    qreal scene_document_width = document()->size().width() * scale(); 

    QString text = toPlainText(); 

    // Once the difference between scene_document_width and the calculated width 
    // is below this value, we accept the new font size. 
    const qreal acceptable_delta = 1.0; 

    // If the difference between scene_document_width and the calculated width is 
    // more than this value, we guess at the new font size by calculating a new 
    // scale factor. Once it is beneath this value, we creep up (or down) by tiny 
    // increments. Without this, we would sometimes incur long "back and forth" 
    // loops when using the scale factor. 
    const qreal creep_delta = 8.0; 
    const qreal creep_increment = 0.1; 

    QScopedPointer<QTextDocument> test_document(document()->clone()); 
    QFont new_font = this->font(); 
    qreal delta = 0.0; 

    // To prevent infinite loops, we store the font size values that we try. 
    // Because of the unpredictable (at least to me) relationship between font 
    // point size and rendering size, this was the only way I could get it to 
    // work reliably. 
    QList<qreal> attempted_font_sizes; 

    while (true) { 

    test_document->setDefaultFont(new_font); 
    delta = scene_document_width - test_document->size().width(); 

    if (std::abs(delta) <= acceptable_delta || 
     attempted_font_sizes.contains(new_font.pointSizeF())) { 
     break; 
    } 

    attempted_font_sizes.append(new_font.pointSizeF()); 

    qreal new_font_size = 0.0; 
    if (std::abs(delta) <= creep_delta) { 
     new_font_size = delta > 0.0 ? new_font.pointSizeF() + creep_increment 
            : new_font.pointSizeF() - creep_increment; 
    } else { 
     new_font_size = new_font.pointSizeF() 
         * scene_document_width 
        /test_document->size().width(); 
    } 
    new_font.setPointSizeF(new_font_size); 
    } 

    this->setFont(new_font); 
    this->setScale(1.0); 
} 
+0

Я думаю, вам может быть лучше с алгоритмом bisecting, который имеет нижнюю границу вашего текущего размера шрифта и как верхнюю границу что-то разумное. Тогда у вас должно быть решение O (log N) для некоторого N, зависящего от ваших данных. –

+0

s/'while (true)'/'forever' / – leemes

0

Другой способ взглянуть на эту проблему: Qt активизировала шрифт, то, что эффективный размер шрифта (как представляется пользователю, а не размер шрифта, заданный в тексте пункта), что мне нужно для отображения пользователю в качестве выбора нового размера шрифта? Это просто альтернатива, вам все равно нужен расчет, похожий на ваш.

У меня есть аналогичная проблема. У меня есть текстовый элемент, который я хочу быть размером единицы (размером одного пикселя), как и мои другие элементы графического элемента (а затем пользователь может масштабировать их.) Какой шрифт (setPointSize) должен быть установлен? (Также, что setTextWidth и что setDocumentMargin?) Преимущество этого дизайна в том, что вам не нужно рассматривать масштабирование текстовых элементов, отличных от масштабирования любой другой фигуры графического элемента. (Но у меня пока нет работы.)

Кроме того, проблема с пользовательским интерфейсом: если пользователь меняет размер шрифта, размер элемента меняется? Или он остается одного и того же размера, а текст обтекает по-разному, оставляя более или менее пустое пространство в конце текста? Когда пользователь добавляет новый текст, меняется ли размер шрифта, поэтому весь текст соответствует размеру фигуры или размер формы увеличивается, чтобы разместить больше текста?Другими словами, это больше похоже на приложение блок-схемы (где размер формы фиксирован и шрифт сжимается) или как приложение текстового редактора (где размер шрифта постоянный, а форма (количество страниц) растет?

 Смежные вопросы

  • Нет связанных вопросов^_^