12

我正在使用 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 文档和网络之后,我无法弄清楚!

谢谢,
克里斯

4

4 回答 4

26

使用类QMatrix。它指定二维变换。QMatrix设置为QPainter

但是请记住,在您的情况下,如果您将小部件的坐标转换为笛卡尔坐标,则必须将第一个点放在(-10,-10) 处(而不是您提到的(-10,10)处)来绘制矩形,其中心在(0,0),因为 Y 轴现在长大,而 X 轴现在长大

您所需要的只是以这种方式转换您的坐标系统:

  • 原点(0,0)转换到小部件的中间:
    替代文字

  • Y 轴缩放-1倍:
    替代文字

这是在小部件功能中键入的代码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 );

结果:
替代文字

2014 年 4 月 7 日更新

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

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

于 2010-12-11T09:26:13.813 回答
3

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

于 2012-03-19T12:40:24.270 回答
2

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

在您的绘画代码中,我们要在坐标 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);
于 2015-09-02T14:03:16.163 回答
1

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

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

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

于 2018-04-03T17:45:32.443 回答