# 用 Ruby Qt 绘图

> 原文： [http://zetcode.com/gui/rubyqt/painting/](http://zetcode.com/gui/rubyqt/painting/)

在 Ruby Qt 编程教程的这一部分中，我们将进行绘图。

我们什么时候需要油漆？ 在某些情况下，当我们需要从头开始创建小部件时。 在这种情况下，我们需要绘图。 或者我们想创建图表，特殊装饰，效果或小部件增强。

当我们在 Qt 库中进行绘图时，`Painter`类将发挥作用。 绘图事件通过`paintEvent`方法接收。 若要进行自定义绘图，我们必须重新实现此方法。

## 图案

在 Qt 中，我们可以使用各种图案来填充形状的内部。

```rb
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws nine rectangles.
# The interiors are filled with
# different built-in patterns.
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp < Qt::Widget

    def initialize
        super

        setWindowTitle "Patterns"

        resize 350, 280
        move 300, 300

        show
    end

    def paintEvent event

        painter = Qt::Painter.new self

        drawPatterns painter
        painter.end
    end

    def drawPatterns painter

        painter.setPen Qt::NoPen

        painter.setBrush Qt::HorPattern
        painter.drawRect 10, 15, 90, 60

        painter.setBrush Qt::VerPattern
        painter.drawRect 130, 15, 90, 60

        painter.setBrush Qt::CrossPattern
        painter.drawRect 250, 15, 90, 60

        painter.setBrush Qt::Dense7Pattern
        painter.drawRect 10, 105, 90, 60

        painter.setBrush Qt::Dense6Pattern
        painter.drawRect 130, 105, 90, 60

        painter.setBrush Qt::Dense5Pattern
        painter.drawRect 250, 105, 90, 60

        painter.setBrush Qt::BDiagPattern
        painter.drawRect 10, 195, 90, 60

        painter.setBrush Qt::FDiagPattern
        painter.drawRect 130, 195, 90, 60

        painter.setBrush Qt::DiagCrossPattern
        painter.drawRect 250, 195, 90, 60
    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec

```

在代码示例中，我们将绘制九个矩形，并用不同的画笔图案填充它们。

```rb
def paintEvent event

    painter = Qt::Painter.new self

    drawPatterns painter
    painter.end
end

```

当需要重绘窗口区域时，将调用`paintEvent`方法。 当我们调整窗口大小，最大化或最小化窗口时，就会发生这种情况。在此方法中，我们创建了`Painter`对象。 该对象用于在 Qt 中进行所有绘制。 绘图本身被委托给`drawPatterns`方法。

```rb
painter.setPen Qt::NoPen

```

笔对象用于绘制形状的轮廓。 在我们的示例中，我们将不使用笔。

```rb
painter.setBrush Qt::HorPattern

```

我们将水平图案设置为画笔。

```rb
painter.drawRect 10, 15, 90, 60

```

我们用当前的笔和画笔绘制一个矩形。 该方法的前两个参数是 x，y 坐标。 最后两个参数是矩形的宽度和高度。

```rb
painter.end

```

`end`方法完成绘制。 释放绘图时使用的所有资源。

![Patterns](img/52e86c7f3212cb66abebfbb142c3be5f.jpg)

图：图案

## 形状

Qt 绘图 API 可以绘制各种形状。 以下编程代码示例将显示其中的一些。

```rb
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws basic shapes
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp < Qt::Widget

    def initialize
        super

        setWindowTitle "Basic shapes"

        resize 350, 280
        move 300, 300

        show
    end

    def paintEvent event

          painter = Qt::Painter.new self

          drawShapes painter
          painter.end
    end

    def drawShapes painter

        painter.setRenderHint Qt::Painter::Antialiasing
        painter.setPen Qt::Color.new 150, 150, 150
        painter.setBrush Qt::Brush.new Qt::Color.new 150, 150, 150

        path1 = Qt::PainterPath.new

        path1.moveTo 5, 5
        path1.cubicTo 40, 5,  50, 50,  99, 99
        path1.cubicTo 5, 99,  50, 50,  5, 5
        painter.drawPath path1

        painter.drawPie 130, 20, 90, 60, 30*16, 120*16
        painter.drawChord 240, 30, 90, 60, 0, 16*180
        painter.drawRoundRect 20, 120, 80, 50

        points = []
        points.push  Qt::Point.new 130, 140
        points.push  Qt::Point.new 180, 170
        points.push  Qt::Point.new 180, 140
        points.push  Qt::Point.new 220, 110
        points.push  Qt::Point.new 140, 100

        polygon = Qt::Polygon.new points

        painter.drawPolygon polygon
        painter.drawRect 250, 110, 60, 60

        baseline = Qt::PointF.new 20, 250
        font = Qt::Font.new "Georgia", 55
        path2 = Qt::PainterPath.new
        path2.addText baseline, font, "Q"
        painter.drawPath path2

        painter.drawEllipse 140, 200, 60, 60
        painter.drawEllipse 240, 200, 90, 60

    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec

```

在此代码示例中，我们在窗口上绘制了九种不同的形状。 复杂路径，饼图，和弦，圆角矩形，多边形，矩形，基于字符的形状，圆形和椭圆形。

```rb
painter.setRenderHint Qt::Painter::Antialiasing

```

我们在示例中使用抗锯齿。 抗锯齿形状看起来更好，但是绘制它们需要更多时间。

```rb
painter.setPen Qt::Color.new 150, 150, 150
painter.setBrush Qt::Brush.new Qt::Color.new 150, 150, 150

```

我们使用深灰色的笔和画笔绘制形状。

```rb
path1 = Qt::PainterPath.new

path1.moveTo 5, 5
path1.cubicTo 40, 5,  50, 50,  99, 99
path1.cubicTo 5, 99,  50, 50,  5, 5
painter.drawPath path1

```

使用`PainterPath`对象创建第一个复杂形状。 `PainterPath`类为绘图操作提供了一个容器。 画家路径是由许多图形构造块（例如矩形，椭圆形，直线和曲线）组成的对象。

```rb
painter.drawPie 130, 20, 90, 60, 30*16, 120*16
painter.drawChord 240, 30, 90, 60, 0, 16*180
painter.drawRoundRect 20, 120, 80, 50

```

这三条线绘制了一个饼图，一个和弦和一个圆角矩形。

```rb
points = []
points.push  Qt::Point.new 130, 140
points.push  Qt::Point.new 180, 170
points.push  Qt::Point.new 180, 140
points.push  Qt::Point.new 220, 110
points.push  Qt::Point.new 140, 100

polygon = Qt::Polygon.new points

painter.drawPolygon polygon

```

我们使用五个点的数组来创建多边形。

```rb
baseline = Qt::PointF.new 20, 250
font = Qt::Font.new "Georgia", 55
path2 = Qt::PainterPath.new
path2.addText baseline, font, "Q"
painter.drawPath path2

```

这些线创建基于字符的形状。

```rb
painter.drawEllipse 140, 200, 60, 60
painter.drawEllipse 240, 200, 90, 60

```

这两条线分别创建一个圆和一个椭圆。

![Shapes](img/5a0b03642d8d98149a6317323a687a73.jpg)

图：形状

## 透明矩形

透明度是能够透视材料的质量。 了解透明度的最简单方法是想象一块玻璃或水。 从技术上讲，光线可以穿过玻璃，这样我们就可以看到玻璃后面的物体。

在计算机图形学中，我们可以使用 alpha 合成实现透明效果。 Alpha 合成是将图像与背景组合以创建部分透明外观的过程。 合成过程使用 Alpha 通道。 （wikipedia.org，answers.com）

```rb
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws ten
# rectangles with different
# levels of transparency.
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp < Qt::Widget

    def initialize
        super

        setWindowTitle "Transparent rectangles"

        resize 590, 90
        move 300, 300

        show
    end

    def paintEvent event

          painter = Qt::Painter.new self

          drawRectangles painter
          painter.end
    end

    def drawRectangles painter

        painter.setPen Qt::NoPen

        for i in 1..10
            painter.setBrush Qt::Brush.new Qt::Color.new 0, 0, 255, i*25
            painter.drawRect 50*i, 20, 40, 40
        end

    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec

```

在示例中，我们将绘制十个具有不同透明度级别的矩形。

```rb
painter.setPen Qt::NoPen

```

我们不用笔。

```rb
for i in 1..10
    painter.setBrush Qt::Brush.new Qt::Color.new 0, 0, 255, i*25
    painter.drawRect 50*i, 20, 40, 40
end

```

`Color`对象的最后一个参数是 alpha 透明度值。

![Transparent rectangles](img/1aaf68c769223b2bf589474509c442ac.jpg)

图：透明矩形

## 甜甜圈形状

在下面的示例中，我们通过旋转一堆椭圆来创建复杂的形状。

```rb
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws a donut
# shape
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp < Qt::Widget

    def initialize
        super

        setWindowTitle "Donut"

        resize 350, 280
        move 300, 300

        show
    end

    def paintEvent event

          painter = Qt::Painter.new self

          drawDonut painter
          painter.end
    end

    def drawDonut painter

        painter.setRenderHint Qt::Painter::Antialiasing

        color = Qt::Color.new
        color.setNamedColor "#333333"

        pen = Qt::Pen.new color
        pen.setWidth 1
        painter.setPen pen

        w = width
        h = height

        painter.translate Qt::Point.new w/2, h/2

        72.times do
            painter.drawEllipse -125, -40, 250, 80
            painter.rotate 5.0
        end
    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec

```

在此示例中，我们创建一个甜甜圈。 形状类似于曲奇，因此得名“甜甜圈”。

```rb
color = Qt::Color.new
color.setNamedColor "#333333"

```

我们可以使用十六进制表示法来创建颜色对象。

```rb
w = width
h = height

```

在这里，我们确定窗口的宽度和高度。

```rb
painter.translate Qt::Point.new w/2, h/2

```

我们将坐标系移到窗口的中间。 这样，我们使绘图在数学上更容易。

```rb
72.times do
    painter.drawEllipse -125, -40, 250, 80
    painter.rotate 5.0
end

```

我们绘制一个椭圆对象 72 次。 每次，我们将椭圆旋转 5 度。 这将创建我们的甜甜圈形状。

![Donut](img/89f87edd19a7fff96b8c12af337ed32e.jpg)

图：多纳圈

## 绘制文字

在最后一个示例中，我们将在窗口上绘制文本。

```rb
#!/usr/bin/ruby

# ZetCode Ruby Qt tutorial
#
# This program draws text
# on the window
#
# author: jan bodnar
# website: www.zetcode.com
# last modified: June 2009

require 'Qt'

class QtApp < Qt::Widget

    def initialize
        super

        setWindowTitle "Soulmate"

        resize 370, 240
        move 300, 300

        show
    end

    def paintEvent event

          painter = Qt::Painter.new self

          drawText painter
          painter.end
    end

    def drawText painter

        painter.setBrush Qt::Brush.new Qt::Color.new 25, 25, 25
        painter.setFont Qt::Font.new "Purisa", 10

        painter.drawText Qt::Point.new(20, 30),
                "Most relationships seem so transitory"
        painter.drawText Qt::Point.new(20, 60),
                "They're good but not the permanent one"
        painter.drawText Qt::Point.new(20, 120),
                "Who doesn't long for someone to hold"
        painter.drawText Qt::Point.new(20, 150),
                "Who knows how to love without being told"
        painter.drawText Qt::Point.new(20, 180),
                "Somebody tell me why I'm on my own"
        painter.drawText Qt::Point.new(20, 210),
                "If there's a soulmate for everyone"

    end
end

app = Qt::Application.new ARGV
QtApp.new
app.exec

```

我们在窗口上画一首歌歌词。

```rb
painter.setFont Qt::Font.new "Purisa", 10

```

我们为文本设置了 Purisa 字体。

```rb
painter.drawText Qt::Point.new(20, 30),
        "Most relationships seem so transitory"

```

`drawText`方法用于绘制文本。

![Drawing text](img/d5e645fb7aabc984012f75b8931ff6e6.jpg)

图：绘制文本

在 Ruby Qt 编程教程的这一部分中，我们做了一些绘图。