原文: http://zetcode.com/gui/vbqyoto/customwidget/

在 Visual Basic Qyoto 编程教程的这一部分中,我们将创建一个自定义窗口小部件。

工具箱通常仅提供最常见的窗口小部件,例如按钮,文本窗口小部件,滑块等。没有工具箱可以提供所有可能的窗口小部件。 程序员必须自己创建此类小部件。 他们使用工具箱提供的绘图工具来完成此任务。 有两种可能性。 程序员可以修改或增强现有的小部件。 或者,他可以从头开始创建自定义窗口小部件。

刻录小部件

在下一个示例中,我们将创建一个自定义刻录小部件。 可以在 Nero 或 K3B 之类的应用中看到此小部件。 该小部件将从头开始创建。

burning.vb

  1. Imports Qyoto
  2. NameSpace Burning
  3. Public Class Burning
  4. Inherits QWidget
  5. Const PANEL_HEIGHT As Integer = 30
  6. Const DISTANCE As Integer = 19
  7. Const LINE_WIDTH As Integer = 5
  8. Const DIVISIONS As Integer = 10
  9. Const FULL_CAPACITY As Double = 700.0
  10. Const MAX_CAPACITY As Double = 750.0
  11. Dim redColor As New QColor(255, 175, 175)
  12. Dim yellowColor As New QColor(255, 255, 184)
  13. Dim parent As QWidget
  14. Dim num() As String = { _
  15. "75", "150", "225", "300", _
  16. "375", "450", "525", "600", _
  17. "675" _
  18. }
  19. Public Sub New(ByVal parent As QWidget)
  20. Me.parent = parent
  21. MinimumHeight = PANEL_HEIGHT
  22. End Sub
  23. Protected Overrides Sub PaintEvent(ByVal e As QPaintEvent)
  24. Dim painter As New QPainter(Me)
  25. Me.DrawWidget(painter)
  26. painter.End()
  27. End Sub
  28. Private Sub DrawWidget(ByVal painter As QPainter)
  29. Dim burn As CustomWidget.VBQApp = CType(parent, CustomWidget.VBQApp)
  30. Dim slid_width As Double = burn.GetCurrentWidth()
  31. Dim width As Double = Size.Width()
  32. Dim move As Double = width / DIVISIONS
  33. Dim till As Double = (width / MAX_CAPACITY) * slid_width
  34. Dim full As Double = (width / MAX_CAPACITY) * FULL_CAPACITY
  35. If slid_width > FULL_CAPACITY
  36. painter.SetPen(New QPen(New QBrush(yellowColor), 1))
  37. painter.SetBrush(New QBrush(yellowColor))
  38. painter.DrawRect(New QRectF(0, 0, full, PANEL_HEIGHT))
  39. painter.SetPen(New QPen(New QBrush(redColor), 1))
  40. painter.SetBrush(New QBrush(redColor))
  41. painter.DrawRect(New QRectF(full+1, 0, till-full, PANEL_HEIGHT))
  42. Else
  43. If (slid_width > 0)
  44. painter.SetPen(New QPen(New QBrush(yellowColor), 1))
  45. painter.SetBrush(New QBrush(yellowColor))
  46. painter.DrawRect(New QRectF(0, 0, till, PANEL_HEIGHT))
  47. End If
  48. End If
  49. painter.SetPen(New QColor(90, 90, 90))
  50. painter.SetBrush(BrushStyle.NoBrush)
  51. painter.DrawRect(0, 0, Size.Width()-1, PANEL_HEIGHT-1)
  52. Dim newFont As QFont = painter.Font()
  53. newFont.SetPointSize(7)
  54. painter.SetFont(newFont)
  55. Dim metrics As New QFontMetrics(newFont)
  56. For i As Integer = 1 to num.Length
  57. painter.DrawLine(New QLineF(i*move, 1, i*move, LINE_WIDTH))
  58. Dim w As Integer = metrics.Width(num(i-1))
  59. painter.DrawText(New QPointF(i*move-w/2, DISTANCE), num(i-1))
  60. Next
  61. End Sub
  62. End Class
  63. End Namespace

在这个文件中,我们创建了刻录小部件。

  1. Public Class Burning
  2. Inherits QWidget

自定义窗口小部件基于QWidget小部件。

  1. Const PANEL_HEIGHT As Integer = 30
  2. Const DISTANCE As Integer = 19
  3. Const LINE_WIDTH As Integer = 5
  4. Const DIVISIONS As Integer = 10
  5. Const FULL_CAPACITY As Double = 700.0
  6. Const MAX_CAPACITY As Double = 750.0

这些是重要的常数。 PANEL_HEIGHT定义自定义窗口小部件的高度。 DISTANCE是比例尺上的数字与其父边框顶部之间的距离。 LINE_WIDTH是垂直线的宽度。 DIVISIONS是秤的数量。 FULL_CAPACITY是媒体的容量。 达到目标后,就会发生过度刻录。 用红色显示。 MAX_CAPACITY是介质的最大容量。

  1. Dim num() As String = { _
  2. "75", "150", "225", "300", _
  3. "375", "450", "525", "600", _
  4. "675" _
  5. }

我们使用这些数字来构建刻录小部件的比例。

  1. Protected Overrides Sub PaintEvent(ByVal e As QPaintEvent)
  2. Dim painter As New QPainter(Me)
  3. Me.DrawWidget(painter)
  4. painter.End()
  5. End Sub

自定义窗口小部件的图形委托给DrawWidget()方法。

  1. Dim burn As CustomWidget.VBQApp = CType(parent, CustomWidget.VBQApp)

我们检索对父窗口小部件的引用。

  1. Dim slid_width As Double = burn.GetCurrentWidth()

我们使用它来获取当前选定的滑块值。

  1. Dim width As Double = Size.Width()

我们得到小部件的宽度。 自定义窗口小部件的宽度是动态的。 用户可以调整大小。

  1. Dim till As Double = (width / MAX_CAPACITY) * slid_width
  2. Dim full As Double = (width / MAX_CAPACITY) * FULL_CAPACITY

我们使用width变量进行转换。 在比例尺值和自定义小部件的度量之间。 请注意,我们使用浮点值。 我们在绘图中获得了更高的精度。

  1. painter.SetPen(New QPen(New QBrush(redColor), 1))
  2. painter.SetBrush(New QBrush(redColor))
  3. painter.DrawRect(New QRectF(full+1, 0, till-full, PANEL_HEIGHT))

这三行画出红色矩形,表示过度燃烧。

  1. painter.DrawRect(0, 0, Size.Width()-1, PANEL_HEIGHT-1)

这是小部件的周长。 外部矩形。

  1. painter.DrawLine(New QLineF(i*move, 1, i*move, LINE_WIDTH))

在这里,我们画出小的垂直线。

  1. Dim w As Integer = metrics.Width(num(i-1))
  2. painter.DrawText(New QPointF(i*move-w/2, DISTANCE), num(i-1))

在这里,我们绘制刻度的数字。 为了精确定位数字,我们必须获得字符串的宽度。

main.vb

  1. Imports Qyoto
  2. ' ZetCode Mono Visual Basic Qt tutorial
  3. '
  4. ' In this program, we create
  5. ' a custom widget
  6. '
  7. ' @author jan bodnar
  8. ' website zetcode.com
  9. ' last modified May 2009
  10. NameSpace CustomWidget
  11. Public Class VBQApp
  12. Inherits QWidget
  13. Const MAX_CAPACITY As Integer = 750
  14. Dim slider As QSlider
  15. Dim widget As QWidget
  16. Dim cur_width As Integer
  17. Public Sub New()
  18. Me.SetWindowTitle("The Burning Widget")
  19. Me.InitUI()
  20. Me.Resize(370, 200)
  21. Me.Move(300, 300)
  22. Me.Show()
  23. End Sub
  24. Private Sub InitUI()
  25. slider = New QSlider(Qt.Orientation.Horizontal , Me)
  26. slider.Maximum = MAX_CAPACITY
  27. slider.SetGeometry(50, 50, 130, 30)
  28. Connect(slider, SIGNAL("valueChanged(int)"), Me, _
  29. SLOT("ValueChanged(int)"))
  30. Dim vbox As New QVBoxLayout(Me)
  31. Dim hbox As New QHBoxLayout
  32. vbox.AddStretch(1)
  33. widget = New Burning.Burning(Me)
  34. hbox.AddWidget(widget, 0)
  35. vbox.AddLayout(hbox)
  36. SetLayout(vbox)
  37. End Sub
  38. <Q_SLOT()> _
  39. Public Sub ValueChanged(ByVal val As Integer)
  40. cur_width = val
  41. widget.Repaint()
  42. End Sub
  43. Public Function GetCurrentWidth() As Integer
  44. Return cur_width
  45. End Function
  46. Public Shared Sub Main(ByVal args() As String)
  47. Dim qapp As New QApplication(args)
  48. Dim app As New VBQApp
  49. QApplication.Exec()
  50. End Sub
  51. End Class
  52. NameSpace CustomWidget

这是主文件。 在这里,我们创建滑块小部件并使用我们的自定义小部件。

  1. widget = New Burning.Burning(Me)
  2. hbox.AddWidget(widget, 0)

我们创建了刻录小部件的实例,并将其添加到水平框中。

  1. <Q_SLOT()> _
  2. Public Sub ValueChanged(ByVal val As Integer)
  3. cur_width = val
  4. widget.Repaint()
  5. End Sub

当滑块的值更改时,我们将其存储在cur_width变量中,然后重新绘制自定义窗口小部件。

  1. Public Function GetCurrentWidth() As Integer
  2. Return cur_width
  3. End Function

定制小部件调用此方法以获取实际的滑块值。

Qyoto 中的自定义小部件 - 图1

图:刻录小部件

在 Visual Basic Qyoto 教程的这一部分中,我们演示了如何创建自定义窗口小部件。