Используйте окно/окно просмотра для переключения Q-оси оси Y

Я использую Qt 4.7 QPainter для рисования нескольких полигонов и т.д. в виджет. Я надеюсь изменить систему координат так, что (0,0) находится в центре моего виджета, а ось x/y ведет себя стандартным "декартовым" способом (т.е. Y увеличивает движение вверх и уменьшается, вниз "). Другими словами, я хочу, чтобы координаты были" математическими ", а не" компьютерной графикой", например, если вы знаете, что я имею в виду.: -)

Я пытаюсь сделать это, используя setViewport() и setWindow(), а не сама математика, так как было бы неплохо просто вызвать методы рисования непосредственно с моими координатами.

Вот что у меня до сих пор:

// Setup coordinates
double screenWidth = width();
double screenHeight = height();

double windowWidth = 100.0;
double windowHeight = (screenHeight / screenWidth) * windowWidth;

painter.setViewport(0, 0, screenWidth, screenHeight);
painter.setWindow(-(windowWidth / 2.0), -(windowHeight / 2.0), windowWidth, windowHeight);

// Draw stuff
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::blue);
painter.drawRect(-10, -10, 20, 20);

Теперь это работает отлично, потому что он рисует красивый синий квадрат в середине экрана. Проблема в том, что я должен сказать, что верхний левый угол (-10, -10). Я хотел бы иметь возможность сделать это (-10, 10), так как это было бы в декартовых мерах.

Я попробовал возиться с setWindow/setViewport, чтобы получить этот "флип" оси y, но безрезультатно. Это кажется очень простой/основной задачей, но после очистки Qt-документов и Интернета я не могу понять это!

Спасибо,
Крис

Ответ 1

Использовать класс QMatrix. Он задает двумерные преобразования. QMatrix установлено значение QPainter.

Но помните, в вашем случае, если вы конвертируете ваши виджеты в декартовы коорды, вам нужно будет поставить первую точку в (- 10, -10) (не в (- 10,10), как вы уже упоминали), чтобы нарисовать прямоугольник с центром в (0,0), поскольку ось Y теперь растет, а X-Axis теперь растет правильно.

Все, что вам нужно, это преобразовать вашу систему координат следующим образом:

  • перевести начало из (0,0) в середину виджета:
    alt text

  • масштаб оси Y по коэффициенту -1:
    alt text

Вот код, набранный функцией paintEvent() виджета:

QPainter pn( this );

int w_2 = width() / 2;
int h_2 = height() / 2;

{ // X- and Y-Axis drawing
    pn.setPen( Qt::blue );
    pn.drawLine( 0, h_2, width(), h_2);     // X-Axis
    pn.drawLine( w_2, 0 , w_2, height() );  // Y-Axis
}

QMatrix m;
m.translate( w_2, h_2 );
m.scale( 1, -1 );

pn.setMatrix( m );
pn.setPen( Qt::NoPen );
pn.setBrush( QBrush( Qt::blue, Qt::Dense4Pattern ) );
pn.drawRect( -10, -10, 20, 20 );

Результат:
alt text

обновление apr 07, 2014

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

Вы правы. Текст также обрабатывается, потому что он рисуется с тем же живописцем. Вы можете нарисовать текст в конце, когда все перевернутые рисунки сделаны, если это возможно. Этот метод не является удобным из-за новых расчетов положения текста. Также вам нужно отбросить настройки для живописца. Теперь я бы рекомендовал вам использовать QGraphicsView из-за огромной поддержки 2D-графики. Также для каждого флага QGraphicsItem ItemIgnoresTransformations можно установить флаг, который позволяет игнорировать унаследованные преобразования (т.е. Его позиция по-прежнему привязана к его родительскому элементу, но игнорирование ротации или просмотра, масштабирование или сдвиговые преобразования игнорируются). Этот флаг полезен для сохранения элементов текстовой метки в горизонтальном и немасштабированном виде, поэтому они будут по-прежнему доступны для чтения, если графическое представление будет преобразовано

Ответ 2

В приведенном выше ответе также будет отображаться текст, "p" будет "b". Чтобы избежать этого, перед тем, как текст будет нарисован, вам нужно отбросить ось y, и вы должны изменить знак на y-coord для текстовой позиции при ее рисовании. Я думаю, это немного уродливо, или есть лучший способ?

Ответ 3

Как указано выше, текст чертежа также отображается с ног на голову. Это простое решение, см. Ниже. Мы временно отключим преобразование мира для рисования текста. Обратите внимание, что текст больше не масштабируется.

в вашем графическом коде мы хотим нарисовать текст по координате QPointF P;

Painter pn( this );

// calculate the point with the transform
QPointF p = pm.transform().map(P);

// Disable Transform temporary
pn.setWorldMatrixEnabled(false);

// draw it ordinary, no scaling etc
pn.drawText(p, QString("HI FRIENDS!"));

// Enable the transform again
pn.setWorldMatrixEnabled(true);