2010-12-10 144 views
10

我正在使用Qt 4.7 QPainter绘制一些多边形,等等到一个小部件。我希望改变坐标系使得(0,0)位于我的小部件的中心,并且x/y轴以标准的“笛卡尔”方式运行(即,y增加“向上”并减小“下”)。换句话说,如果你知道我的意思,我希望坐标是“数学”,而不是“计算机图形”。 :-)使用窗口/视口翻转QPainter 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文档和网页之后,我无法弄清楚!

谢谢,
克里斯

回答

22

使用类QMatrix。它指定了2D转换。 QMatrix设置为QPainter

但要记住,你的情况,如果转换Widget的COORDS到笛卡尔COORDS,你将不得不把第一点(-10,-10)(不(-10,10 )因为你没有提到的)绘制一个矩形,其在(0,0中心),因为Y轴现在长大了 X轴现在的增长

所有你需要的是这种方式将您的坐标系统:

  • 翻译起源(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

更新2014年4月7日

这问题很久以前就被问到了许多事情自那以来已经改变对于那些今天(2014年初)他们自问相同的问题,我个人的回答是,自Qt 4.3以后,可以更轻松地解决文本翻转问题。

你说得对。文本也被填满,因为它是用同一个画家绘制的。如果可能,可以在所有翻转图纸完成时在最后绘制文本。由于文本位置的新计算,此方法不方便。你也需要放弃画家的设置。 现在我建议你使用QGraphicsView,因为2D绘画的巨大支持。也可以设置每个QGraphicsItemItemIgnoresTransformations标志,该标志允许忽略继承的转换(即,其位置仍然锚定到其父项,但忽略父视图或视图旋转,缩放或剪切转换)。此标志对于保持文本标签项目水平和非缩放非常有用,因此如果图形视图已转换,它们仍然可读。

+1

正确,但是需要提及的是,文本也会翻转。这大多是不期望的! – bkausbk 2014-03-24 12:50:11

+0

感谢您的更新;) – Stormenet 2014-12-09 17:06:13

3

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

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);