simples Balkendiagramm
Verfasst: 08.08.2009 14:29
ein Balkendiagramm um Daten grafisch darzustellen, hatten wir sicher schon oft, aber ich finde noch eins kann nicht schaden.
Es ist sicher nicht perfekt, aber als Grundlage für Anfänger sicher brauchbar. Mir reicht es.
im Beispiel sind es 31 Balken = 31 Tage. Mehr Balken sind möglich, aber bei
zu vielen Balken sieht es nicht mehr gut aus.
In der Höhe skaliert es sich automatisch, abhängig vom Maxwert im Datenfeld. Die Werte sollten 6 Stellen nicht überschreiten
Weitere Erklärungen im Code
Es läuft bei mir unter Windows XP 32 Bit
Noch etwas zum Experimentieren, ein Code um Text gedreht auszugeben, um unten Wörter hinzusetzen.
Man muß dann aber in der Zeile, baseY = winhh - chrhh * 3, aus der 3 eventuell eine 6 machen.
Und anstatt von DrawText_ DrawTextR aufrufen.
__________________________________________________
Thread wurde verschoben
Anfänger>Code, Tipps und Tricks
08.08.2009
RSBasic
Es ist sicher nicht perfekt, aber als Grundlage für Anfänger sicher brauchbar. Mir reicht es.
im Beispiel sind es 31 Balken = 31 Tage. Mehr Balken sind möglich, aber bei
zu vielen Balken sieht es nicht mehr gut aus.
In der Höhe skaliert es sich automatisch, abhängig vom Maxwert im Datenfeld. Die Werte sollten 6 Stellen nicht überschreiten
Weitere Erklärungen im Code
Es läuft bei mir unter Windows XP 32 Bit
Code: Alles auswählen
Procedure Balkendiagramm2(info$, Array dinfo$(1), Array daten(1), parent)
;sollte ein Fix-Font sein !!!
fontnr = LoadFont(#PB_Any, "Courier New", 8)
winbr = 600
winhh = 400
winnr = OpenWindow(#PB_Any,0,0,winbr,winhh,info$,#PB_Window_SystemMenu|1,WindowID(parent))
;max des Datenfeldes finden
size = ArraySize(daten())
For j = 0 To size
If daten(j) > maxwert: maxwert = daten(j): EndIf
Next
;Mod wert x
Select maxwert
Case 0 To 10: x = 1
Case 11 To 100: x = 10
Case 101 To 1000: x = 10
Case 1001 To 10000: x = 100
Case 10001 To 100000: x = 100
Default: x = 1000
EndSelect
;max des Datenfeldes bis nächsten glatten Wert erhöhen
While maxwert % x ;für senkrechte Y Skala
maxwert + 1
Wend
; -----------------------------------------------------------------
;nur für Höhe + Breite eines Zeichens, sollte Fix-Font sein
StartDrawing(WindowOutput(winnr))
DrawingFont(FontID(fontnr))
chrbr = TextWidth("X")
chrhh = TextHeight("X")
StopDrawing()
balken = ArraySize(daten())
rows = 10
baseX = chrbr * 7 ;senkrechte Linie vom linken Fensterrand
baseY = winhh - chrhh * 3 ;waagerechte Linie von unten
;Balkenabstand in Pixel, -1 kann auch wegfallen
pixelX = ((winbr - baseX) / balken) - 1
If pixelX < 1: pixelX = 1: EndIf ;null verhindern
scaleY = maxwert / rows ;Abstand der Zahlen pro Reihe
pixelY = baseY / rows ;Abstand der Reihen in Pixel
If scaleY < 1: scaleY = 1: EndIf ;null verhindern
If pixelY < 1: pixelY = 10: EndIf
nr = CreateImage(#PB_Any, winbr, winhh, 16) ;16 Bit Farbtiefe
dc = StartDrawing(ImageOutput(nr))
Box(0, 0, winbr, winhh, #White)
Line(baseX, 0, 0, baseY, #Blue) ;senkrechteLinie
Line(baseX, baseY, winbr - baseX, 0, #Blue) ;waagerechte Linie
; gestrichelte Linien + Text links der senkrechten Linie
DrawingFont(FontID(fontnr))
pen = CreatePen_(#PS_DOT,0,#Gray) ;für gestrichelte Linie
SelectObject_(dc,pen)
r.rect
y = baseY ;Basis unten für 0
For j = 0 To rows
If j
MoveToEx_(dc, baseX, y, 0)
LineTo_(dc, winbr, y) ;gestrichelte Linie
EndIf
txt$ = Str(scaleY * j) ;Text links z.B.0,5,10,15...50
r\top = y - chrhh / 3
r\left = 0
r\right = baseX - 2
r\bottom = r\top + chrhh
SetTextAlign_(dc, #TA_TOP)
DrawText_(dc, txt$, -1, r, 2) ;2 = #DT_RIGHT
y - pixelY ;Y-Pixelwert ist für nächste Zahl
Next
DeleteObject_(pen)
; -------------------------------------------
baseX + 4 ;etwas Abstand zur senkrechten Linie für Text + Balken
;Text unten für Balken
altX = 0
For j = 1 To balken
x = baseX + ((j-1) * pixelX) ;pixelposi für nächsten Balken
txt$ = dinfo$(j)
breite = TextWidth(txt$)
br = breite: If pixelX > breite: br = pixelX: EndIf
If altX + br <= x ;kein Platz, kein Text
r\top = baseY + 3 ;r.rect definiert den Raum für Text
r\left = x - 2 ; -2 um baseX + 4 auszugleichen
r\right = r\left + br ; + br ist Textbreite oder Balkenabstand
r\bottom = r\top + TextHeight(txt$)
SetTextAlign_(dc, #TA_TOP) ;ohne geht nix
DrawText_(dc, txt$, -1, r, 1) ;1 = #DT_CENTER
;DrawTextR(dc, r, txt$, 90, 0, 12)
altX = x
InflateRect_(r,1,1) ;vergrößert r.rect für DrawEdge
DrawEdge_(dc,r,1,#BF_RECT) ;nur für die Optik
EndIf
Next
;Balken
balkenbr = pixelX - 4
If balkenbr < 1: balkenbr = 1: EndIf
For j = 1 To balken
lh = (daten(j) * pixelY) / scaleY ;höhe des Balken
x = baseX + ((j-1) * pixelX) ;pixelposi für nächsten Balken
farbe = #Cyan ;
If lh > 3 * pixelY: farbe = #Blue: EndIf
If lh > 6 * pixelY: farbe = #Green: EndIf
Box(x, baseY, balkenbr, -lh, farbe) ;-lh, damit Balken von unten
Next ; nach oben gemalt wird
StopDrawing()
ImageGadget(#PB_Any,0,0, 0,0,ImageID(nr))
FreeFont(fontnr)
ProcedureReturn winnr
EndProcedure
Procedure BalkenDiagramm(main)
;zwischen geschobene Prozedur, welche die Daten bereitstellt
DisableWindow(main, 1)
max = 31 ;31 Balken
Dim tt$(max)
Dim dtn(max)
For j = 1 To max
tt$(j) = Str(j)
dtn(j) = Random(441) ;Wert zwischen 0 und 441
Next
ProcedureReturn Balkendiagramm2(Str(max) + " Werte", tt$(), dtn(), main)
EndProcedure
;------------------------------------
main = 0
OpenWindow(main,0,0,800,600,"",#PB_Window_SystemMenu|1)
subwin = Balkendiagramm(main)
Repeat: event = WaitWindowEvent()
If event = #PB_Event_CloseWindow
If EventWindow() = subwin
event = 0
DisableWindow(0, 0)
CloseWindow(subwin)
EndIf
EndIf
Until event = #PB_Event_CloseWindow
End
Man muß dann aber in der Zeile, baseY = winhh - chrhh * 3, aus der 3 eventuell eine 6 machen.
Und anstatt von DrawText_ DrawTextR aufrufen.
Code: Alles auswählen
Procedure DrawTextR(dc, *r.rect, txt$, angle, fontid, fontsize, quality=2)
; Diese Procedure gibt gedrehten Text aus
GetObject_(fontid,SizeOf(LOGFONT),NewFont.LOGFONT)
NewFont\lfEscapement = angle * 10
NewFont\lfHeight = fontsize
NewFont\lfWeight = quality*100
hFont = CreateFontIndirect_(NewFont)
oldFont = SelectObject_(dc,hFont)
*r\bottom + 5 ; diesen Wert bei Wörtern erhöhen
SetTextAlign_(dc, #TA_RIGHT)
DrawText_(dc, txt$, -1, *r, 1) ;1 = #DT_CENTER
SelectObject_(dc,oldFont)
DeleteObject_(hFont)
EndProcedure
Thread wurde verschoben
Anfänger>Code, Tipps und Tricks
08.08.2009
RSBasic