使用窗口/视口翻转QPainter y轴

时间:2010-12-10 21:43:19

标签: qt graphics qt4 coordinates qpainter

我正在使用Qt 4.7 QPainter将一些多边形等绘制到一个小部件中。我希望改变坐标系,使得(0,0)位于我的小部件的中心,并且x / y轴以标准的“笛卡尔”方式运行(即,y增加“向上”并且减少“下”)。换句话说,如果你知道我的意思,我希望坐标是“数学” - 而不是“计算机图形”。 : - )

我正在尝试使用setViewport()和setWindow()而不是自己做数学,因为能够直接用我的坐标调用draw方法会很好。

这是我到目前为止所得到的:

// 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文档和网页之后,我无法理解它!

谢谢,
克里斯

4 个答案:

答案 0 :(得分:23)

使用班级QMatrix。它指定了2D变换。 QMatrix设置为QPainter

但请记住,在您的情况下,如果您将小部件的坐标转换为笛卡尔坐标,则必须将第一个点放在( - 10,-10) < em>(不是你提到的( - 10,10))绘制一个矩形,其中心位于(0,0),因为Y轴现在增长 up ,X轴现在增长正确

您只需要以这种方式改变您的坐标系:

  • 原点(0,0)翻译到小部件的中间位置:
    alt text

  • -1 因子缩放 Y轴
    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

更新2014年4月7日

很久以前就提出过这个问题,很多事情都发生了变化。对于那些今天(2014年初)问自己同样问题的人,我的个人答案是,从Qt 4.3开始,可以更轻松地解决文本翻转问题。

你是对的。文本也会被删除,因为它是使用相同的画家绘制的。如果可能的话,您可以在完成所有翻转的绘图时在最后绘制文本。由于文本位置的新计算,这种方法不方便。此外,您还需要删除画家的设置。 现在我建议你使用QGraphicsView,因为2D绘画的巨大支持。同样可以设置每个QGraphicsItem ItemIgnoresTransformations标志,这允许它忽略继承的变换(即,它的位置仍然锚定到其父级,但父级或视图旋转,缩放或剪切变换被忽略)。此标志对于使文本标签项保持水平和未缩放非常有用,因此如果图形视图已转换,它们仍可读取

答案 1 :(得分:3)

上述答案也将翻转文字,“p”将为“b”。为避免在绘制文本之前必须翻转y轴,并且在绘制文本时必须在y-coord上更改文本位置的符号。我认为这有点难看,还是有更好的方法?

答案 2 :(得分:1)

如上所述,绘图文字也会颠倒翻转。有一个简单的解决方案,见下文。我们将临时禁用文本绘制的世界变换。请注意,文本不再缩放。

在你的绘画代码中,我们想在坐标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);

答案 3 :(得分:0)

我需要翻转y轴,以便使用来自Java坐标中定义的点的Qt绘制线条和多边形。我想其他人需要在从Java移植到Qt坐标系时这样做。上面的讨论很有帮助。我的解决方案是:

painter.translate(0,height());
painter.scale(1.0, -1.0);

然后继续绘制线条和多边形。