Grundlegend für das Zeichnen auf einer Zeichenfläche (Canvas, Device) wie einer DrawingArea sind die Betrachtungen im Buch-Kapitel '3.3.3 Zeichnen mit Paint' sowie die folgenden Kapitel 'Paint-Projekte 1' und 'Paint-Projekte 2'.
Im ersten Projekt wird auf der Basis einer Datenreihe ein Streifen-Diagramm gezeichnet und passend beschriftet. Als Zeichenfläche dient eine DrawingArea:
Abbildung 18.11.1.0.1: GUI BarChart – Streifen-Diagramm – 'Finanzbericht 2023'
Der hinreichend kommentierte Quelltext mit allen Zeichnen-Prozeduren wird komplett angegeben:
' Gambas class file Public xTranslate As Float Public yTranslate As Float Public xScale As Float = 1 Public yScale As Float = -1 Public Sub Form_Open() FMain.Resizable = False FMain.Arrangement = Arrange.Vertical FMain.Margin = True FMain.Spacing = True DrawingAreaCanvas.Expand = True End Public Sub DrawingAreaCanvas_Draw() '-- Draw the bar chart. The canvas is a DrawingArea. DrawBarChart() End Public Sub DrawBarChart() Dim i As Integer Dim fDeltaX, fDeltaY, fOffsetX, fEndX, fEndY, fMaxValue As Float Dim aData, aDataC As Float[] Dim sCaption As String Dim iBarColor As Integer Dim aColorMatrix As New Integer[] aColorMatrix = [16691968, 14682169, 3673255, 10666574, 7840196, 15165856, 652969, / 4340047, 12119436, 14775582, 4752276, 160484] '-- Inline array with the barchart values to be displayed aData = [2.2, 4, 2.4, 5.4, 3, 5.0, 5.7, 3.6, 4.5, 2.0, 1.6, 3.2] aDataC = aData.Copy() '-- Copy of the array of original values aDataC.Sort(gb.Descent) '-- Descending sorting of the copy elements fMaxValue = aDatac[0] '-- The 1st element is now the largest value in the copied array fOffsetX = 10 '-- Definition of the abscissa offset ► +10 fEndX = 540 '-- Definition of fixed coordinates for the size fEndY = 240 fDeltaX = Round((fEndX - fOffsetX) / aData.Count, 0) '-- Normalised strip width (unit) fDeltaY = Round(fEndY / fMaxValue, 0) '-- Normalised strip height (unit) xTranslate = 40.0 yTranslate = 320.0 Paint.Translate(xTranslate, yTranslate) Paint.Scale(1, -1) ' +y ▲ SetOrigin() Draw_X_Axis() Draw_Y_Axis() Draw_Y_AxisArrow() '-- Labelling Caption Paint.Scale(1, -1) ' +y ▼ sCaption = ("Financial Report 2023") Paint.Font = Font["Monospace, 12"] Paint.DrawText(sCaption, 385, -290) Paint.Scale(1, -1) ' +y ▲ '-- All 12 financial values are drawn as stripes For i = 0 To aData.Max '-- Calculation and drawn of all stripes (rectangles) in the diagram with stripe color iBarColor = aColorMatrix[i] Paint.FillRect(fOffsetX + i * fDeltaX, 1.3, fDeltaX, fDeltaY * aData[i], iBarColor) Paint.Scale(1, -1) ' +y ▼ Paint.Brush = Paint.Color(Color.Black) Paint.Font = Font["Monospace, 10"] Paint.DrawText(Str(aData[i]), fOffsetX + i * fDeltaX, -fDeltaY * aData[i] - 30, fDeltaX, 30, Align.Center) Paint.Font = Font["Monospace, 10"] Paint.DrawText(Str(i + 1), fOffsetX + i * fDeltaX, 1, fDeltaX, 30, Align.Center) Paint.Scale(1, -1) Next '-- Labelling the y-axis Paint.Scale(1, -1) ' +y ▼ sCaption = ("Value in 10^4 €") Paint.Font = Font["Monospace, 9"] If Paint.TextSize(sCaption).W / 2 > xTranslate Then Paint.DrawText(sCaption, 0 - xTranslate / 2, -290) Else Paint.DrawText(sCaption, 0 - Paint.TextSize(sCaption).W / 2, -290) Endif Paint.Scale(1, -1) End Public Sub DrawingAreaCanvas_MouseDown() '-- Display of the (relative) coordinates - for tests only Print Str(Mouse.X - xTranslate) & " | " & Str(-Mouse.Y + yTranslate) End '-------------------------------------------------------------------------------------- Private Sub SetOrigin() '-- Origin of coordinates Paint.Brush = Paint.Color(Color.Red) Paint.MoveTo(0, 0) Paint.Arc(0, 0, 4) Paint.Fill() Paint.Brush = Paint.Color(Color.Black) End Private Sub Draw_X_Axis() '-- x-axis Paint.AntiAlias = False Paint.MoveTo(-20, 0) Paint.LineTo(560, 0) Paint.Stroke() Paint.AntiAlias = True End Private Sub Draw_Y_Axis() '-- y-axis Paint.AntiAlias = False Paint.MoveTo(0, -20) Paint.LineTo(0, 270) Paint.MoveTo(0, 0) Paint.Stroke() Paint.AntiAlias = True End Private Sub Draw_Y_AxisArrow() Dim i As Integer '-- y-axis (arrow) Paint.AntiAlias = False For i = 1 To 5 Paint.MoveTo(-6 + i, 264 + i) Paint.LineTo(7 - i, 264 + i) Paint.Stroke() Next Paint.AntiAlias = True End '-------------------------------------------------------------------------------------- Public Sub ButtonClose_Click() FMain.Close() End
Hinweise
Das Besondere an diesem Projekt sind die erweiterten Forderungen gegenüber dem ersten Projekt, denn der Inhalt der DrawingArea mit dem Streifen-Diagramm soll
Auf den Inhalt einer DrawingArea können Sie nicht direkt zugreifen.
Sie können beim Druck in eine Datei im Dialog als Ausgabeformat PDF oder PostScript oder SVG auswählen oder das Image auf einem Drucker wie einem Laserdrucker ausdrucken.
Abbildung 18.11.1.1.1: GUI BarChart – Streifen-Diagramm in der DrawingArea
Abbildung 18.11.1.1.2: Ausdruck in eine Datei – 3 Formate
Abbildung 18.11.1.1.3: (Druck-)Vorschau
Abbildung 18.11.1.1.4: Ausdruck auf einen Drucker – FS-1030D
Abbildung 18.11.1.1.5: Drucken – Seite einrichten
Der hinreichend kommentierte Quelltext wird auch für das zweite Projekt komplett angegeben, um die Umsetzung des o.a. Konzeptes zu verdeutlichen. Anschließende Hinweise ergänzen die Kommentare:
(1) ' Gambas class file (2) (3) Public hPicture As Picture (4) Public hImage As Image (5) (6) Public xTranslate As Float (7) Public yTranslate As Float (8) Public xScale As Float = 1 (9) Public yScale As Float = -1 (10) (11) (12) Public Sub Form_Open() (13) (14) FMain.Resizable = False (15) FMain.Arrangement = Arrange.Vertical (16) FMain.Margin = True (17) FMain.Spacing = True (18) (19) DrawingAreaCanvas.Expand = True (20) (21) '-- Draw the bar chart. The canvas is a picture (hPicture)! (22) DrawBarChart() (23) '-- Draw the picture in the DrawingArea by raising its _Draw event (24) DrawingAreaCanvas.Refresh() (25) (26) End (27) (28) Public Sub DrawingAreaCanvas_Draw() (29) (30) Paint.DrawPicture(hPicture, 0, 0) (31) (32) End (33) (34) Public Sub DrawBarChart() (35) (36) Dim i As Integer (37) Dim fDeltaX, fDeltaY, fOffsetX, fEndX, fEndY, fMaxValue As Float (38) Dim aData, aDataC As Float[] (39) Dim sCaption As String (40) Dim iBarColor As Integer (41) Dim aColorMatrix As Integer[] (42) (43) aColorMatrix = [16691968, 14682169, 3673255, 10666574, 7840196, 15165856, 652969, 4340047, 12119436, 14775582, 4752276, 160484] (44) (45) '-- Creation of a object with defined size of type Picture (46) hPicture = New Picture(DrawingAreaCanvas.W, DrawingAreaCanvas.H) (47) hPicture.Fill(&HF0F0F0) (48) (49) Paint.Begin(hPicture) (50) '-- Inline array with the values to be displayed (51) aData = [2.2, 4, 2.4, 5.4, 3, 5.0, 5.7, 3.6, 4.5, 2.0, 1.6, 3.2] (52) aDataC = aData.Copy() '-- Copy of the array of original values (53) aDataC.Sort(gb.Descent) '-- Descending sorting of the copy elements (54) fMaxValue = aDatac[0] '-- The 1st element is now the largest value in the copied array (55) (56) fOffsetX = 10 '-- Definition of the abscissa offset ↦ +10 (57) fEndX = 540 '-- Definition of fixed coordinates for the size (58) fEndY = 240 (59) fDeltaX = Round((fEndX - fOffsetX) / aData.Count, 0) '-- Normalised strip width (unit) (60) fDeltaY = Round(fEndY / fMaxValue, 0) '-- Normalised strip height (unit) (61) (62) xTranslate = 40.0 (63) yTranslate = 320.0 (64) Paint.Translate(xTranslate, yTranslate) (65) Paint.Scale(1, -1) ' +y ▲ (66) (67) SetOrigin() (68) Draw_X_Axis() (69) Draw_Y_Axis() (70) Draw_Y_AxisArrow() (71) (72) '-- Labelling Caption (73) Paint.Scale(1, -1) ' +y ▼ (74) sCaption = ("Financial Report 2023") (75) Paint.Font = Font["Monospace, 12"] (76) Paint.DrawText(sCaption, 385, -290) (77) Paint.Scale(1, -1) ' +y ▲ (78) (79) '-- All 12 financial values are drawn as stripes (80) For i = 0 To aData.Max (81) '-- Calculation and drawn of all stripes (rectangles) in the diagram with stripe color (82) iBarColor = aColorMatrix[i] (83) Paint.FillRect(fOffsetX + i * fDeltaX, 1.2, fDeltaX, fDeltaY * aData[i], iBarColor) (84) Paint.Scale(1, -1) ' +y ▼ (85) Paint.Brush = Paint.Color(Color.Black) (86) Paint.Font = Font["Monospace, 10"] (87) Paint.DrawText(Str(aData[i]), fOffsetX + i * fDeltaX, -fDeltaY * aData[i] - 30, fDeltaX, 30, Align.Center) (88) Paint.Font = Font["Monospace, 10"] (89) Paint.DrawText(Str(i + 1), fOffsetX + i * fDeltaX, 1, fDeltaX, 30, Align.Center) (90) Paint.Scale(1, -1) (91) Next (92) (93) '-- Labelling the y-axis (94) Paint.Scale(1, -1) ' +y ▼ (95) sCaption = ("Value in 10^4 €") (96) Paint.Font = Font["Monospace, 9"] (97) If Paint.TextSize(sCaption).W / 2 > xTranslate Then (98) Paint.DrawText(sCaption, 0 - xTranslate / 2, -290) (99) Else (100) Paint.DrawText(sCaption, 0 - Paint.TextSize(sCaption).W / 2, -290) (101) Endif (102) Paint.Scale(1, -1) (103) Paint.End() (104) (105) '-- The content of the Picture (current canvas) is assigned to an image that is used for printing (106) hImage = hPicture.Image (107) (108) End (109) (110) Public Sub ButtonSaveBarChart_Click() (111) (112) hPicture.Save(Application.Path &/ "chart/barchart.png") (113) (114) End (115) (116) Public Sub ButtonPrintBarChart_Click() (117) (118) Printer1.Paper = Printer1.A4 (119) Printer1.Orientation = Printer.Landscape (120) (121) '-- Color printing is standard and therefore not required as a specification (122) Printer1.GrayScale = False (123) Printer1.FullPage = True '-- Should always be used! (124) (125) Printer1.NumCopies = 1 (126) If Printer1.NumCopies > 1 Then (127) Printer1.ReverseOrder = True (128) Printer1.CollateCopies = True (129) Else (130) Printer1.ReverseOrder = False (131) Printer1.CollateCopies = False (132) Endif (133) (134) '-- Definition of the 4 margins with fixed margin values (135) Printer1.MarginLeft = 30 (136) Printer1.MarginTop = 30 (137) Printer1.MarginRight = 100 (138) Printer1.MarginBottom = 10 (139) (140) Printer1.OutputFile = User.Home &/ "bilanz_bc_2023.pdf" (141) (142) If Printer1.Configure() Then Return (143) Printer1.Print() (144) (145) End (146) (147) Public Sub Printer1_Begin() (148) (149) Printer1.Count = 1 '-- This specification ( > 0 ) is required (150) (151) End (152) (153) Public Sub Printer1_Draw() (154) (155) Dim fPrintW, fPrintH As Float (156) Dim fRatioImage As Float (157) (158) Paint.Scale(Paint.Width / Printer1.PaperWidth, Paint.Height / Printer1.PaperHeight) (159) Paint.Translate(Printer1.MarginLeft, Printer1.MarginTop) (160) (161) fRatioImage = hImage.W / hImage.H (162) fPrintW = Printer1.PaperWidth - (Printer1.MarginLeft + Printer1.MarginRight) (163) fPrintH = Printer1.PaperHeight - (Printer1.MarginTop + Printer1.MarginBottom) (164) (165) '-- Match diagram rectangle into the target format (166) If fRatioImage > (Paint.W / Paint.H) Then (167) Paint.DrawImage(hImage, 0, 0, fPrintW, fPrintW / fRatioImage) (168) Else (169) Paint.DrawImage(hImage, 0, 0, fPrintH / fRatioImage, fPrintH) (170) Endif (171) (172) End (173) (174) '-------------------------------------------------------------------------------------- (175) (176) Private Sub SetOrigin() (177) (178) '-- Origin of coordinates (179) Paint.Brush = Paint.Color(Color.Red) (180) Paint.MoveTo(0, 0) (181) Paint.Arc(0, 0, 4) (182) Paint.Fill() (183) Paint.Brush = Paint.Color(Color.Black) (184) (185) End (186) (187) Private Sub Draw_X_Axis() (188) (189) '-- x-axis (190) Paint.AntiAlias = False (191) Paint.MoveTo(-20, 0) (192) Paint.LineTo(560, 0) (193) Paint.Stroke() (194) Paint.AntiAlias = True (195) (196) End (197) (198) Private Sub Draw_Y_Axis() (199) (200) '-- y-axis (201) Paint.AntiAlias = False (202) Paint.MoveTo(0, -20) (203) Paint.LineTo(0, 270) (204) Paint.MoveTo(0, 0) (205) Paint.Stroke() (206) Paint.AntiAlias = True (207) (208) End (209) (210) Private Sub Draw_Y_AxisArrow() (211) (212) Dim i As Integer (213) (214) '-- y-axis (arrow) (215) Paint.AntiAlias = False (216) For i = 1 To 5 (217) Paint.MoveTo(-6 + i, 264 + i) (218) Paint.LineTo(7 - i, 264 + i) (219) Paint.Stroke() (220) Next (221) Paint.AntiAlias = True (222) (223) End (224) (225) '-------------------------------------------------------------------------------------- (226) (227) (228) Public Sub Form_Close() (229) (230) Dim hWindow As Window (231) (232) '-- Close all open windows (233) For Each hWindow In Windows (234) hWindow.Close() (235) Next (236) (237) End
Die Hinweise beziehen sich auf die Zeilen 265 bis 270 im o.a. Quelltext
'-- Match diagram rectangle into the target format IF fRatioImage > (Paint.W / Paint.H) THEN Paint.DrawImage(hImage, 0, 0, fPrintW, fPrintW / fRatioImage) ELSE Paint.DrawImage(hImage, 0, 0, fPrintH / fRatioImage, fPrintH) ENDIF
Für den ersten Fall gilt: Die Breite des BarChart entspricht der verfügbaren Breite des Druckbereichs. Die Höhe wird entsprechend der Original-Proportionen errechnet:
Abbildung 18.11.1.1.6: BarChart – Druckbreite
Für den zweiten Fall gilt: Die Höhe des BarChart entspricht der verfügbaren Höhe des Druckbereichs. Die Breite wird entsprechend der Original-Proportionen errechnet:
Abbildung 18.11.1.1.7: BarChart – Druckhöhe
Den Quelltext für die beiden Projekte finden Sie in zwei Projekt-Archiven im Download-Bereich.