原文: http://zetcode.com/gui/csharpqyoto/painting/

在 Qyoto C# 编程教程的这一部分中,我们将进行绘图。

当我们在京都进行绘图时,QPainter类非常有用。 绘图事件通过OnPaintEvent()方法接收。 若要进行自定义绘图,我们必须重新实现此方法。

图案

在《京都议定书》中,我们可以使用各种图案来填充形状的内部。

  1. using System;
  2. using QtCore;
  3. using QtGui;
  4. /**
  5. * ZetCode Qyoto C# tutorial
  6. *
  7. * This program draws nine rectangles.
  8. * The interiors are filled with
  9. * different built-in patterns.
  10. *
  11. * @author Jan Bodnar
  12. * website zetcode.com
  13. * last modified November 2012
  14. */
  15. public class QyotoApp : QMainWindow
  16. {
  17. public QyotoApp()
  18. {
  19. WindowTitle = "Patterns";
  20. PaintEvent += OnPaintEvent;
  21. Resize(350, 280);
  22. Move(300, 300);
  23. Show();
  24. }
  25. private void OnPaintEvent(object sender, QEventArgs<QPaintEvent> e)
  26. {
  27. QPainter ptr = new QPainter(this);
  28. DrawPatterns(ptr);
  29. ptr.End();
  30. }
  31. void DrawPatterns(QPainter ptr)
  32. {
  33. ptr.SetPen(Qt.PenStyle.NoPen);
  34. ptr.SetBrush(Qt.BrushStyle.HorPattern);
  35. ptr.DrawRect(10, 15, 90, 60);
  36. ptr.SetBrush(Qt.BrushStyle.VerPattern);
  37. ptr.DrawRect(130, 15, 90, 60);
  38. ptr.SetBrush(Qt.BrushStyle.CrossPattern);
  39. ptr.DrawRect(250, 15, 90, 60);
  40. ptr.SetBrush(Qt.BrushStyle.Dense7Pattern);
  41. ptr.DrawRect(10, 105, 90, 60);
  42. ptr.SetBrush(Qt.BrushStyle.Dense6Pattern);
  43. ptr.DrawRect(130, 105, 90, 60);
  44. ptr.SetBrush(Qt.BrushStyle.Dense5Pattern);
  45. ptr.DrawRect(250, 105, 90, 60);
  46. ptr.SetBrush(Qt.BrushStyle.BDiagPattern);
  47. ptr.DrawRect(10, 195, 90, 60);
  48. ptr.SetBrush(Qt.BrushStyle.FDiagPattern);
  49. ptr.DrawRect(130, 195, 90, 60);
  50. ptr.SetBrush(Qt.BrushStyle.DiagCrossPattern);
  51. ptr.DrawRect(250, 195, 90, 60);
  52. }
  53. [STAThread]
  54. public static int Main(String[] args)
  55. {
  56. new QApplication(args);
  57. new QyotoApp();
  58. return QApplication.Exec();
  59. }
  60. }

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

  1. PaintEvent += OnPaintEvent;

在绘制事件中执行绘制。 我们将OnPaintEvent()方法插入到绘画事件。

  1. private void OnPaintEvent(object sender, QEventArgs<QPaintEvent> e)
  2. {
  3. QPainter ptr = new QPainter(this);
  4. DrawPatterns(ptr);
  5. ptr.End();
  6. }

当需要重绘窗口区域时,将调用OnPaintEvent()方法。 当我们调整窗口大小,最大化或最小化窗口时,就会发生这种情况。在此方法中,我们创建了QPainter对象。 该对象用于完成 Qyoto 中的所有绘图。 绘图本身被委托给DrawPatterns()方法。 End()方法释放绘图时使用的资源。

  1. ptr.SetPen(Qt.PenStyle.NoPen);

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

  1. ptr.SetBrush(Qt.BrushStyle.HorPattern);

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

  1. ptr.DrawRect(10, 15, 90, 60);

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

Qyoto 中的绘图 - 图1

图:图案

形状

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

  1. using System;
  2. using System.Collections.Generic;
  3. using QtGui;
  4. using QtCore;
  5. /**
  6. * ZetCode Qyoto C# tutorial
  7. *
  8. * This program draws basic shapes
  9. * available in Qyoto.
  10. *
  11. * @author Jan Bodnar
  12. * website zetcode.com
  13. * last modified November 2012
  14. */
  15. public class QyotoApp : QMainWindow
  16. {
  17. public QyotoApp()
  18. {
  19. WindowTitle = "Shapes";
  20. PaintEvent += OnPaintEvent;
  21. Resize(350, 280);
  22. Move(300, 300);
  23. Show();
  24. }
  25. private void OnPaintEvent(object sender, QEventArgs<QPaintEvent> e)
  26. {
  27. QPainter ptr = new QPainter(this);
  28. DrawShapes(ptr);
  29. ptr.End();
  30. }
  31. void DrawShapes(QPainter ptr)
  32. {
  33. ptr.SetRenderHint(QPainter.RenderHint.Antialiasing);
  34. ptr.Pen = new QPen(new QBrush(new QColor("Gray")), 1);
  35. ptr.Brush = new QColor("Gray");
  36. QPainterPath path1 = new QPainterPath();
  37. path1.MoveTo(5, 5);
  38. path1.CubicTo(40, 5, 50, 50, 99, 99);
  39. path1.CubicTo(5, 99, 50, 50, 5, 5);
  40. ptr.DrawPath(path1);
  41. ptr.DrawPie(130, 20, 90, 60, 30*16, 120*16);
  42. ptr.DrawChord(240, 30, 90, 60, 0, 16*180);
  43. ptr.DrawRoundRect(20, 120, 80, 50);
  44. List<QPoint> points = new List<QPoint>();
  45. points.Add(new QPoint(130, 140));
  46. points.Add(new QPoint(180, 170));
  47. points.Add(new QPoint(180, 140));
  48. points.Add(new QPoint(220, 110));
  49. points.Add(new QPoint(140, 100));
  50. QPolygon polygon = new QPolygon(points);
  51. ptr.DrawPolygon(polygon);
  52. ptr.DrawRect(250, 110, 60, 60);
  53. QPointF baseline = new QPointF(20, 250);
  54. QFont font = new QFont("Georgia", 55);
  55. QPainterPath path2 = new QPainterPath();
  56. path2.AddText(baseline, font, "Q");
  57. ptr.DrawPath(path2);
  58. ptr.DrawEllipse(140, 200, 60, 60);
  59. ptr.DrawEllipse(240, 200, 90, 60);
  60. }
  61. [STAThread]
  62. public static int Main(String[] args)
  63. {
  64. new QApplication(args);
  65. new QyotoApp();
  66. return QApplication.Exec();
  67. }
  68. }

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

  1. ptr.SetRenderHint(QPainter.RenderHint.Antialiasing);

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

  1. ptr.Pen = new QPen(new QBrush(new QColor("Gray")), 1);
  2. ptr.Brush = new QColor("Gray");

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

  1. QPainterPath path1 = new QPainterPath();
  2. path1.MoveTo(5, 5);
  3. path1.CubicTo(40, 5, 50, 50, 99, 99);
  4. path1.CubicTo(5, 99, 50, 50, 5, 5);
  5. ptr.DrawPath(path1);

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

  1. ptr.DrawPie(130, 20, 90, 60, 30*16, 120*16);
  2. ptr.DrawChord(240, 30, 90, 60, 0, 16*180);
  3. ptr.DrawRoundRect(20, 120, 80, 50);

这三行画出一个饼图,一个和弦和一个圆角矩形。

  1. List<QPoint> points = new List<QPoint>();
  2. points.Add(new QPoint(130, 140));
  3. points.Add(new QPoint(180, 170));
  4. points.Add(new QPoint(180, 140));
  5. points.Add(new QPoint(220, 110));
  6. points.Add(new QPoint(140, 100));
  7. QPolygon polygon = new QPolygon(points);
  8. ptr.DrawPolygon(polygon);

我们使用五个点的列表来创建多边形。

  1. QPointF baseline = new QPointF(20, 250);
  2. QFont font = new QFont("Georgia", 55);
  3. QPainterPath path2 = new QPainterPath();
  4. path2.AddText(baseline, font, "Q");
  5. ptr.DrawPath(path2);

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

  1. ptr.DrawEllipse(140, 200, 60, 60);
  2. ptr.DrawEllipse(240, 200, 90, 60);

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

Qyoto 中的绘图 - 图2

图:形状

透明矩形

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

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

  1. using System;
  2. using QtCore;
  3. using QtGui;
  4. /**
  5. * ZetCode Qyoto C# tutorial
  6. *
  7. * This program draws ten rectangles with
  8. * different levels of transparency.
  9. *
  10. * @author Jan Bodnar
  11. * website zetcode.com
  12. * last modified November 2012
  13. */
  14. public class QyotoApp : QMainWindow
  15. {
  16. public QyotoApp()
  17. {
  18. WindowTitle = "Transparent rectangles";
  19. PaintEvent += OnPaintEvent;
  20. Resize(590, 90);
  21. Move(300, 300);
  22. Show();
  23. }
  24. private void OnPaintEvent(object sender, QEventArgs<QPaintEvent> e)
  25. {
  26. QPainter ptr = new QPainter(this);
  27. DrawRectangles(ptr);
  28. ptr.End();
  29. }
  30. void DrawRectangles(QPainter ptr)
  31. {
  32. ptr.SetPen(Qt.PenStyle.NoPen);
  33. for (int i=1; i<11; i++)
  34. {
  35. ptr.Brush = new QColor(0, 0, 255, i*25);
  36. ptr.DrawRect(50*i, 20, 40, 40);
  37. }
  38. }
  39. [STAThread]
  40. public static int Main(String[] args)
  41. {
  42. new QApplication(args);
  43. new QyotoApp();
  44. return QApplication.Exec();
  45. }
  46. }

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

  1. ptr.SetPen(Qt.PenStyle.NoPen);

我们不用笔。

  1. for (int i=1; i<11; i++)
  2. {
  3. ptr.Brush = new QColor(0, 0, 255, i*25);
  4. ptr.DrawRect(50*i, 20, 40, 40);
  5. }

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

Qyoto 中的绘图 - 图3

图:透明矩形

绘制文字

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

  1. using System;
  2. using QtCore;
  3. using QtGui;
  4. /**
  5. * ZetCode Qyoto C# tutorial
  6. *
  7. * This program draws text
  8. * on the window.
  9. *
  10. * @author Jan Bodnar
  11. * website zetcode.com
  12. * last modified November 2012
  13. */
  14. public class QyotoApp : QMainWindow
  15. {
  16. public QyotoApp()
  17. {
  18. WindowTitle = "Soulmate";
  19. PaintEvent += OnPaintEvent;
  20. Resize(370, 240);
  21. Move(300, 300);
  22. Show();
  23. }
  24. private void OnPaintEvent(object sender, QEventArgs<QPaintEvent> e)
  25. {
  26. QPainter ptr = new QPainter(this);
  27. DrawLyrics(ptr);
  28. ptr.End();
  29. }
  30. void DrawLyrics(QPainter ptr)
  31. {
  32. ptr.Brush = new QColor(25, 25, 25);
  33. ptr.Font = new QFont("Courier", 10);
  34. ptr.DrawText(new QPoint(20, 30),
  35. "Most relationships seem so transitory");
  36. ptr.DrawText(new QPoint(20, 60),
  37. "They're good but not the permanent one");
  38. ptr.DrawText(new QPoint(20, 120),
  39. "Who doesn't long for someone to hold");
  40. ptr.DrawText(new QPoint(20, 150),
  41. "Who knows how to love without being told");
  42. ptr.DrawText(new QPoint(20, 180),
  43. "Somebody tell me why I'm on my own");
  44. ptr.DrawText(new QPoint(20, 210),
  45. "If there's a soulmate for everyone");
  46. }
  47. [STAThread]
  48. public static int Main(String[] args)
  49. {
  50. new QApplication(args);
  51. new QyotoApp();
  52. return QApplication.Exec();
  53. }
  54. }

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

  1. ptr.Font = new QFont("Courier", 10);

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

  1. ptr.DrawText(new QPoint(20, 30),
  2. "Most relationships seem so transitory");

DrawText()方法用于在x = 20y = 30处绘制文本。

Qyoto 中的绘图 - 图4

图:绘制文本

在 Qyoto C# 编程教程的这一部分中,我们做了一些绘图。