[VB.NET] Hokjes inkleuren mbv de muis

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • HnD
  • Registratie: December 2009
  • Laatst online: 27-08 19:33
Hallo,

Ik probeer met visual basic 2010 een programma te maken die gegevens naar een printje kan sturen via de com-poort. Dit gaat wel lukken denk ik maar in het programma moet een wiel komen waar hokjes in staan zoals in de afbeelding hieronder.

Dit is wel gelukt maar nu wil ik dat je deze hokjes kunt inkleuren met behulp van de muis. De positie van de muis heb ik al maar het inkleuren van de hokjes wil niet echt. Bij normale vierkantjes kan ik wel een kleurtje geven, nog niet met behulp van de muis, maar omdat deze hokjes uit snijdende lijnen bestaat vroeg ik me af hoe je het nu moet inkleuren.

Als dat kan moet het programma ook nog bijhouden welke hokjes zijn ingekleurd, er zitten 16 hokjes onder elkaar dus het zo mooi zijn als dat in 2 bytes kan zodat ik het verder kan gebruiken op het printje.


Afbeeldingslocatie: http://lh5.ggpht.com/_9XIEEnS5wz4/Szs_dvVDj6I/AAAAAAAAAPs/SZ6EqNF8prE/VB%20wiel.JPG

Dit is de code die ik heb gebruikt om een rondje te maken met de hokjes erin.

Visual Basic: prog
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    Private Sub Form1_Paint(ByVal sender As Object, ByVal e _
    As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint


        e.Graphics.DrawEllipse(Pens.Black, Center_x - Radius, Center_y - Radius, 2 * Radius, 2 * Radius)


        For Degrees = 0 To 360 Step 2.8125
            Angle = Math.PI * Degrees / 180.0
            X_cor = Center_x + Radius * Math.Cos(Angle)
            Y_cor = Center_y + Radius * Math.Sin(Angle)
            e.Graphics.DrawLine(Pens.Black, Center_x, Center_y, X_cor, Y_cor)
        Next

        e.Graphics.DrawEllipse(Pens.Black, Center_x - Radius, Center_y - Radius, 2 * Radius, 2 * Radius)

        For Round = 0 To 128 Step 8
            e.Graphics.DrawEllipse(Pens.Black, Center_x - Radius + Round + 20, Center_y - Radius + Round + 20, 2 * (Radius - Round - 20), 2 * (Radius - Round - 20))
        Next

    End Sub


Mvg,

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:10
Dat is lastig op de huidige manier, want je tekent nu lijnen en niet hokjes. Om hokjes in te kleuren kun je ofwel een bitmap gebruiken en dan op de juiste punten floodfillen, maar dat is niet erg mooi om te printen (je moet dan een behoorlijk grote bitmap gebruiken om op hoge resolutie af te drukken). Als je met GDI primitieven wil tekenen, kun je beter een manier zoeken om vakjes te benaderen met een polygoon of een spline, en inkleuren door eerst de gekleurde vakjes te tekenen en daarna nog eens de lijnen erovereen.

Het inkleuren met de muis is op zichzelf niet zoveel ingewikkelder, maar het vereist dat je op basis van schermcoordinaten (de positie van de muis op het scherm) terug kunt rekenen welk vakje in de tekening aangewezen is. Dat hoeft niet zo'n probleem te zijn, omdat je dat makkelijk kunt bepalen aan de hand van de poolcoördinaten van de muispointer ten opzichte van het middelpunt van de cirkel.

[ Voor 5% gewijzigd door Soultaker op 30-12-2009 13:32 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Soultaker schreef op woensdag 30 december 2009 @ 13:31:
maar dat is niet erg mooi om te printen (je moet dan een behoorlijk grote bitmap gebruiken om op hoge resolutie af te drukken).
Zoals ik het lees gaat het niet om te printen, maar om de gegevens naar een printje ( oftewel een of andere device wat aan de COM poort hangt ) te sturen. Het gaat er dan volgens mij ook alleen om om het visueel weer te geven.

Daar zul je inderdaad eerst de stap moeten maken om je muis/scherm coordinaten om te rekenen naar coordinaten in je tekening, en aan de hand daarvan moeten bepalen welk vakje je moet kleuren.

Daarna kun je inderdaad kiezen om of een soort flood-fill te doen of het met een polygon renderen

offtopic:
Overigens is het VB.NET. VB 2010 is de IDE waar je in werkt ;)

[ Voor 4% gewijzigd door Woy op 30-12-2009 15:16 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Het mooiste is denk ik als je de omtrek van zo'n vakje ziet als een te vullen path. Scheelt ook weer in bestandsgrootte bij printers met support of 'onechte' printers (zoals pdf). Voor de buitenste ring heb je dan dus:
Visual Basic:
1
2
3
4
5
6
7
8
9
10
        Dim graphPath As New GraphicsPath
        Dim no As Single = 10
        With graphPath
            .AddArc(Center_x - Radius, Center_y - Radius, 2 * Radius, 2 * Radius, 
                2.8125F * no, 2.8125F)
            .AddArc(Center_x - Radius + 20, Center_y - Radius + 20, 2 * Radius - 40, 
                2 * Radius - 40, 2.8125F * (no + 1), -2.8125F)
            .CloseFigure()
        End With
        Graphic.FillPath(Brushes.Red, graphPath)

En voor de binnenste ringen is het bijna hetzelfde.

Maak van dit soort plaatjes trouwens altijd een PNG, geen JPG. JPG geeft artifacts en is voor foto's. ;)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:10
Als GDI paths met cirkelbogen ondersteunt, is dat inderdaad een mooiere oplossing dan benaderen met splines of polygonen.
Woy schreef op woensdag 30 december 2009 @ 15:15:
Zoals ik het lees gaat het niet om te printen, maar om de gegevens naar een printje ( oftewel een of andere device wat aan de COM poort hangt ) te sturen.
Oh, dat had ik wellicht verkeerd begrepen. Nou ja, tekenen op het scherm werkt verder hetzelfde als naar een printer in principe.

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Soultaker schreef op woensdag 30 december 2009 @ 16:13:
Als GDI paths met cirkelbogen ondersteunt [...]
Let op: dit is GDI+, geen GDI. ;) Dat heeft een aantal voordelen, zoals dat je eventueel ook anti-aliasing kan gebruiken (zie oa Graphic.SmoothingMode). Dat zorgt er dan voor dat een floodfill overigens kansloos is, en die zit dan ook niet in GDI+ bij mijn weten..

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 13:10
Dat begrijp ik; het idee was meer dat als 't echt niet anders kan, je nog altijd een bitmap ter grootte van je window kan maken, daarin floodfillen (desnoods handmatig, zo ingewikkeld is 't niet) en het resultaat blitten. Dat moet ook onder GDI+ nog wel kunnen, lijkt me.

Zo'n aanpak heeft niet de voorkeur omdat het traag is en veel geheugen vereist. Je voorstel met een path is veel beter. :)

Acties:
  • 0 Henk 'm!

  • HnD
  • Registratie: December 2009
  • Laatst online: 27-08 19:33
Okay bedankt voor de reacties ik zal eens kijken of ik wat op het scherm krijg. Ik ben een tijdje ziek geweest dus daarom werd het reageren wat lastig maar ik zal er nu weer eens verder mee.

Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 06:48

Sebazzz

3dp

pedorus schreef op woensdag 30 december 2009 @ 16:54:
[...]

Dat zorgt er dan voor dat een floodfill overigens kansloos is, en die zit dan ook niet in GDI+ bij mijn weten..
Tsja, het is maar hoe je het aanpakt. Wat nou als je inderdaad floodfilled, maar qua pixel dat je gaat inkleuren een bepaalde marge qua kleurverschil overhoudt? Dan ziet er al beter is. Desnoods onthou je hoeveel de kleur afwijkt van zwart zodat je een tintje zwart doet door de kleur die je de pixel gaat geven.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Even voorop gesteld dat een vector-oplossing natuurlijk veel mooier is:
Sebazzz schreef op woensdag 06 januari 2010 @ 16:54:
[...]
Tsja, het is maar hoe je het aanpakt. Wat nou als je inderdaad floodfilled, maar qua pixel dat je gaat inkleuren een bepaalde marge qua kleurverschil overhoudt? Dan ziet er al beter is. Desnoods onthou je hoeveel de kleur afwijkt van zwart zodat je een tintje zwart doet door de kleur die je de pixel gaat geven.
Op zich kun je best een floodfill doen, maar welke marge ga je aanhouden? Als je heel netjes wil werken moet je dan op 99.5% zwart gaan zitten ofzo, omdat dat soort gevallen ook voor komen. Als de lijn dan niet dik genoeg is, kom je geen 100% zwarte pixel meer tegen, en dan ga je er dus overheen... Tuurlijk, op zich zijn dit details in de marge. ;)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • HnD
  • Registratie: December 2009
  • Laatst online: 27-08 19:33
Ik heb het nu met path's gedaan dit lukt wel aardig maar om nou 1 voor 1 die hokjes in het programma te zetten lijkt me niet erg handig (als het kan zoals ik wil moeten dat er 1024 worden dus..).

Dus dacht ik dat je dat met een for - next lusje wel goed kunt oplossen maar nu wou ik een array maken van het GraphicsPath en dat schijnt niet te kunnen. Weet iemand hier misschien een oplossing voor?

Ik heb nu gewoon een tellertje gemaakt die van 0 tot 127 loopt en zo de hokjes tekent dus ik dacht van met die teller het nummer van de array aangeven maar zoals gezegd werkt dit dus niet.

Mvg,

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
HnD schreef op donderdag 07 januari 2010 @ 20:05:
Ik heb het nu met path's gedaan dit lukt wel aardig maar om nou 1 voor 1 die hokjes in het programma te zetten lijkt me niet erg handig (als het kan zoals ik wil moeten dat er 1024 worden dus..).
Ik dacht dat het om 128*(17-1)=2048 vakjes ging? ;) Maar het lijkt me ook dat je gewoon 1 methode hebt om een willekeurig vakje te kleuren indien nodig.
Dus dacht ik dat je dat met een for - next lusje wel goed kunt oplossen maar nu wou ik een array maken van het GraphicsPath en dat schijnt niet te kunnen. Weet iemand hier misschien een oplossing voor?
Ik zie niet in waarom je perse een array van GraphicsPaths zou willen hebben. Dat kan wel (gewoon steeds een nieuw object maken met New), maar lijkt me niet zo nodig, je kan er bijvoorbeeld gewoon 1 steeds hergebruiken (Reset aanroepen), of gebruikmaken van meerdere Figures in het Path (als alles dezelfde kleur moet hebben). Het lijkt me meer dat je een dubbel for-loopje hebt die aan de hand van een multi-dimensionale array de juiste vakjes kleurt. Als je 2 mogelijkheden per vakje hebt, zou je een BitArray kunnen gebruiken als je heel efficiënt met geheugen wil omgaan (zoiets haal ik uit je TS), maar 2048 waardes opslaan is sowieso niet zo boeiend.
Ik heb nu gewoon een tellertje gemaakt die van 0 tot 127 loopt en zo de hokjes tekent dus ik dacht van met die teller het nummer van de array aangeven maar zoals gezegd werkt dit dus niet.
Wat heb je precies geprobeerd dan? Eigenlijk lijkt me dit probleem voortkomen uit onvoldoende basis-programmeerkennis, dus in die zin zal een VB.NET tutorial wel helpen.. ;)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • HnD
  • Registratie: December 2009
  • Laatst online: 27-08 19:33
De code die ik nu heb is misschien wat vaag en kan misschien wat compacter maar hij tekent de hokjes. Nu wou ik die teller gebruiken om de aparte hokjes aan de geven als aparte paths. Dus zegmaar zoiets als: Wiel(hoekG) en dat als je bijvoorbeeld hokje 50 wilt inkleuren dat je dan e.Graphics.DrawPath(New Pen(Color.Black, 1), Wiel(50)) kunt invullen. maar dat kan niet dus weet iemand hoe je hetzelfde resultaat zou krijgen zonder arrays te gebruiken.


Visual Basic .NET: prog
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
        
For HoekG = 0 To 127 Step 1
            With Wiel
                '--------------------------------------------------------------------------------------------------------------------------
                Dx = Midx - Straal
                Dy = Midy - Straal

                hoekSt = HoekG * 2.8125
                HoekSw = HoekG * 2.8125 + 2.8125

                .AddArc(Dx, Dy, 2 * Straal, 2 * Straal, hoekSt, 2.8125)


                '--------------------------------------------------------------------------------------------------------------------------


                HoekR = Math.PI * (HoekG + 1) * 2.8125 / 180.0

                Px = Midx + Straal * Math.Cos(HoekR)
                Py = Midy + Straal * Math.Sin(HoekR)

                Qx = Midx + (Straal - 20) * Math.Cos(HoekR)
                Qy = Midy + (Straal - 20) * Math.Sin(HoekR)

                .AddLine(Px, Py, Qx, Qy)


                '--------------------------------------------------------------------------------------------------------------------------


                Fx = Midx - Straal + 20
                Fy = Midy - Straal + 20

                .AddArc(Fx, Fy, 2 * (Straal - 20), 2 * (Straal - 20), HoekSw, -2.8125)


                '--------------------------------------------------------------------------------------------------------------------------


                HoekR = Math.PI * HoekG * 2.8125 / 180.0

                Tx = Midx + (Straal - 20) * Math.Cos(HoekR)
                Ty = Midy + (Straal - 20) * Math.Sin(HoekR)

                Sx = Midx + Straal * Math.Cos(HoekR)
                Sy = Midy + Straal * Math.Sin(HoekR)

                .AddLine(Tx, Ty, Sx, Sy)


                '--------------------------------------------------------------------------------------------------------------------------


                .AddArc(Dx, Dy, 2 * Straal, 2 * Straal, hoekSt, 2.8125)
            End With

        Next


Mvg

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
HnD schreef op vrijdag 08 januari 2010 @ 14:46:
De code die ik nu heb is misschien wat vaag en kan misschien wat compacter maar hij tekent de hokjes.
Ik dacht dat de code in de TS al hokjes tekende, en dat je ze nu wilde inkleuren? :) Het lijkt me logisch om eerst wat vlakjes te tekenen waar nodig, en dan gewoon de code in de TS uit te voeren..
Nu wou ik die teller gebruiken om de aparte hokjes aan de geven als aparte paths. Dus zegmaar zoiets als: Wiel(hoekG) en dat als je bijvoorbeeld hokje 50 wilt inkleuren dat je dan e.Graphics.DrawPath(New Pen(Color.Black, 1), Wiel(50)) kunt invullen. maar dat kan niet dus weet iemand hoe je hetzelfde resultaat zou krijgen zonder arrays te gebruiken.
Er is al een simpele zwarte pen, dus je hoeft geen nieuwe te maken: Pens.Black. Je kan toch gewoon een functie maken die een GraphicsPath getourneerd? Iets als:
Visual Basic:
1
Function WielVlakje(nummer as Integer) as GraphicsPath

Met bijna dezelfde code als in mijn post. Er zijn dus maar twee aanroepen nodig naar .AddArc, de lijnen worden er automatisch bij bedacht (als je een Fill doet is zelfs CloseFigure() niet nodig).

Ik zou trouwens gewoon alle code in het Engels houden, en dus geen Nederlandse namen gebruiken.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • HnD
  • Registratie: December 2009
  • Laatst online: 27-08 19:33
pedorus schreef op vrijdag 08 januari 2010 @ 16:59:

Ik dacht dat de code in de TS al hokjes tekende, en dat je ze nu wilde inkleuren?
Ja maar is het niet makkelijker om dan ook gewoon met die paths hokjes te tekenen?
pedorus schreef op vrijdag 08 januari 2010 @ 16:59:

Er is al een simpele zwarte pen, dus je hoeft geen nieuwe te maken: Pens.Black. Je kan toch gewoon een functie maken die een GraphicsPath getourneerd
Ja dat was een foutje van mij eigenlijk moest hij niet het hokje tekenen maar het hokje inkleuren, als je op een bepaald punt klikt met je muis dan moet dus bijvoorbeeld hokje 50. Maar laat ik de vraag anders stellen:

kun de naam van een GraphicsPath afhankelijk maken van een variabele (integer)?
Dus bijvoorbeeld Wiel1 en de volgende Wiel2.
pedorus schreef op vrijdag 08 januari 2010 @ 16:59:

Ik zou trouwens gewoon alle code in het Engels houden, en dus geen Nederlandse namen gebruiken.
Ja dit wil ik later denk ik weer aanpassen als alles werkt en dan direct ook wat duidelijker de variabelen declareren + commentaar maar omdat ik nu nog aan het proberen ben vind ik het makkelijker om dit even in het Nederlands te doen. :)

Mvg,

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
HnD schreef op vrijdag 08 januari 2010 @ 21:35:
Ja maar is het niet makkelijker om dan ook gewoon met die paths hokjes te tekenen?
Dat zou kunnen, maar je hebt die code nu toch al. :) Daarnaast is het het mooiste om niet dezelfde lijn 2x te tekenen, of op te splitsen in deeltjes. Dit levert een verschil op als je naar een PDF-printer print, bijvoorbeeld (de vector-afbeelding wordt dan onnodig groter).
Ja dat was een foutje van mij eigenlijk moest hij niet het hokje tekenen maar het hokje inkleuren, als je op een bepaald punt klikt met je muis dan moet dus bijvoorbeeld hokje 50. Maar laat ik de vraag anders stellen:

kun de naam van een GraphicsPath afhankelijk maken van een variabele (integer)?
Dus bijvoorbeeld Wiel1 en de volgende Wiel2.
Dit lijkt mij een vraag die komt door onvoldoende basiskennis. :) Dit kan, maar variabelen als Wiel1, Wiel2, Wiel3, etc. zijn bijna nooit wat je wilt. Wat je dan wilt is een array, dus in VB Wiel(1), of in C# (wat mijn persoonlijke voorkeur heeft) Wiel[1]. In principe kun je makkelijk 2048 nieuwe GraphicsPath-objecten opslaan in een array, ook in VB. Omdat dit meer werk is, en weinig winst oplevert, is het handiger om bijvoorbeeld gewoon een functie te maken, en daarin Reset() aan te roepen. In principe is een regeltje of 15 aan VB.NET-code genoeg om alle 2048 vlakjes al dan niet te kleuren, dus dat kan prima in 1 Sub TekenVlakjes(vakjesKleur(,) as Color, g as Graphics) oid. In deze sub staan dan bijvoorbeeld 2 for-loopjes, en bijvoorbeeld de code die ik al heb gegeven met een IIf voor de buitenste ring.

En ik denk dat het bij het aanklikken van een vakje het makkelijkst is om het juiste vakje in een array te zetten, en de boel gewoon compleet opnieuw te tekenen (met Invalidate).

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • HnD
  • Registratie: December 2009
  • Laatst online: 27-08 19:33
Ik heb inderdaad nog niet heel veel ervaring met visual basic maar ik begrijp nu wel wat je bedoeld dus ik kan nu bijvoorbeeld hokje 6 en hokje 100 wel inkleuren. Dus heel erg bedankt voor je voorbeeldjes en informatie :)

Ik zal nu wat proberen met de muis en daarna nog de uitlezing van de hokjes en deze in bytes te zetten zodat de PIC ermee overweg kan.

Mvg,
Pagina: 1