Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C#] - Paint Programma

Pagina: 1
Acties:

  • JST94
  • Registratie: Juli 2009
  • Laatst online: 31-07 13:28
Beste Tweaker(s),

Ik ben op het moment bezig een soort programma als Paint te maken. Ik ben aan het proberen om een lijn te tekenen op mijn beeldscherm. Deze lijn word getekend door middel van een MouseMove event. Ook moet ik mijn linkermuisknop hebben ingehouden wil ik de lijn kunnen tekenen. Deze lijn MOET getekend worden binnen een picturebox. Ik heb al het een ander geprobeerd, maar ik kom er maar niet uit. Hebben jullie misschien ideeën of tips hoe ik dit probleem wel kan oplossen?

C#:
1
2
3
4
5
6
7
8
        // Declaratie variabelen
        Color colorPen = Color.Black;
        int thickLine = 1;

        Bitmap image1;
        bool Tekenen;
        int startX;
        int startY;


Hierin laad ik een image (geheel wit vierkant, op de afmetingen van de PictureBox) in de PictureBox. Een klasgenoot gaf dit als tip om te kunnen tekenen.
C#:
1
2
3
4
5
        private void Form1_Load(object sender, EventArgs e)
        {
            image1 = new Bitmap(Properties.Resources.Image);
            pB.Image = (Image)image1;
        }


Hier zet ik de boolean Tekenen op true, zodat hij in het MouseMove event kan tekenen. De locaties van waar de lijn moet worden getekent worden gezet in startX en startY.
C#:
1
2
3
4
5
6
        private void pB_MouseDown(object sender, MouseEventArgs e)
        {
                Tekenen = true;
                startX = e.Location.X;
                startY = e.Location.Y;
        }


Hier het MouseMove event van waar de lijn moet worden getekend. Aangezien je op muisbeweging moet tekenen. Had ik in gedachte dat je telkens het einde van de lijn het nieuwe beginpunt is van de nieuwe lijn.

De lijn moet trouwens een vloeiende lijn zijn, ik had al eerst iets anders weten te maken. Maar zodra ik snel van de linker naar rechterkant ging, dan kwamen er witten stukken tussen de lijnen te staan.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
        private void pB_MouseMove(object sender, MouseEventArgs e)
        {
            int eindX = startX;
            int eindY = startY;

            startX = e.X;
            startY = e.Y;

            if (Tekenen == true)
            {
                Graphics G = Graphics.FromImage(image1);
                Pen Pen1 = new Pen(colorPen, thickLine);
                GraphicsPath Path = new GraphicsPath(
                new Point[]
                {
                    new Point(startX, startY),
                    new Point(eindX, eindY)
                },
                new byte[]
                {
                    (byte)PathPointType.Start,
                    (byte)PathPointType.Line
                });

                G.DrawPath(Pen1, Path);
                G.Save();
                pB.Image = image1;
            }

        }



Ik hoop dat jullie me iets verder op weg kunnen helpen. :)

  • Tim14ww
  • Registratie: Januari 2011
  • Laatst online: 13-08 09:55
Dit is zeker een schoolproject? wel lekker makkelijk om dit hier op te gooien, vind je niet...? Ik zou beginnen om dat laatste stuk eens weg te knallen.

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
JustMU schreef op dinsdag 10 september 2013 @ 13:04:
Ik heb al het een ander geprobeerd, maar ik kom er maar niet uit. Hebben jullie misschien ideeën of tips hoe ik dit probleem wel kan oplossen?
Waar kom je precies niet uit? Je laat wel mooi zien wat je gemaakt heb, maar ik weet nog niet waar je precies tegen aan loopt? Wat werkt er niet zoals verwacht? Heb je dat al gedebugd?
C#:
1
2
3
4
5
6
        private void pB_MouseDown(object sender, MouseEventArgs e)
        {
                Tekenen = true;
                startX = e.Location.X;
                startY = e.Location.Y;
        }


Hier het MouseMove event van waar de lijn moet worden getekend. Aangezien je op muisbeweging moet tekenen. Had ik in gedachte dat je telkens het einde van de lijn het nieuwe beginpunt is van de nieuwe lijn.

De lijn moet trouwens een vloeiende lijn zijn, ik had al eerst iets anders weten te maken. Maar zodra ik snel van de linker naar rechterkant ging, dan kwamen er witten stukken tussen de lijnen te staan.
C#:
1
2
3
4
5
6
7
        private void pB_MouseMove(object sender, MouseEventArgs e)
        {
            if (Tekenen == true)
            {
            }

        }
Je weet dat je aan die MouseEventArgs gewoon kunt zien of de mouse button down is. Dat hoef je dus niet meer zelf bij te houden met een aparte variabele.

@Tim14ww: Ook huiswerk staan we hier gewoon toe, alleen het initiatief moet wel bij de TS liggen, het is dus niet dat wij hier kant en klare oplossingen aan gaan dragen zonder dat de TS zelf moeite doet om zijn probleem te achterhalen.

[ Voor 8% gewijzigd door Woy op 10-09-2013 14:22 ]

“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.”


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Woy schreef op dinsdag 10 september 2013 @ 14:21:
@Tim14ww: Ook huiswerk staan we hier gewoon toe, alleen het initiatief moet wel bij de TS liggen, het is dus niet dat wij hier kant en klare oplossingen aan gaan dragen zonder dat de TS zelf moeite doet om zijn probleem te achterhalen.
Ofwel: Huiswerktopics zijn niet per definitie fout! :Y)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • JST94
  • Registratie: Juli 2009
  • Laatst online: 31-07 13:28
Woy schreef op dinsdag 10 september 2013 @ 14:21:
[...]

Waar kom je precies niet uit? Je laat wel mooi zien wat je gemaakt heb, maar ik weet nog niet waar je precies tegen aan loopt? Wat werkt er niet zoals verwacht? Heb je dat al gedebugd?

[...]

Je weet dat je aan die MouseEventArgs gewoon kunt zien of de mouse button down is. Dat hoef je dus niet meer zelf bij te houden met een aparte variabele.

...
Ah oke, ik moet net zoals in Paint kunnen tekenen. Ik heb dus een picturebox aangemaakt. Dit is het vak waarin getekend moet worden. Eerder was het me via een opdracht al gelukt om een lijn (ofja, een rondje) te tekenen. Dit was niet in een Picturebox. Alleen als ik snel van links naar rechts ga dan komen er stukken 'wit' tussen.

Ik moet dus een plaatje openen (dit werkt gewoon) en daar moet ik dan op kunnen 'tekenen'. Ik moet een lijndikte selecteren en een kleur en dan moet ik in de picturebox het plaatje kunnen bewerken. De lijndikte selecteren en de kleur is het probleem niet. De lijn op zichzelf tekenen wel. Dat komt omdat de lijn vloeiend moet zijn. Het mag niet zoals bij het rondje dat als je snel van links naar rechts gaat dat er stukken wit tussen komen te zitten.

Ik dacht dus dat je als je klikt worden de X en Y waarde geregistreert. Vervolgens als je de muis beweegt tekent hij een lijn naar de X en Y waarde. Vervolgens zet hij de X en Y waarde waar je als laatst op staat met je muis in de beginvariabele, als je dan weer verder beweegt zet hij die nieuwe waarde weer in de eindvariabelen. Dan word daartussen weer een lijn getekend. Zo gaat dat continue door als je je muisknop houd ingedrukt. Op het moment dat je hem loslaat stopt hij met tekenen. Als je dan weer je muis indrukt ergens anders in de picturebox zet hij die waarde weer in de startvariabele en begint hij vanaf daar weer mee te tekenen met je muisbewegingen.

Enig idee hoe ik dit kan oplossen? Andere klasgenoot had het erover dat het erg omslachtig is met een bitmap.

Ik weet niet of ik het duidelijk heb uitgelegt, maar ik hoop dat je er wat van snapt.

Verwijderd

Als je een vloeiende lijn wilt tekenen zonder gaten, dan moet je in je mousemove event de positie van de laatste mousemove event opslaan, en dan een lijn tussen die 2 punten tekenen.

Als je het nog preciezer wilt kun je denken aan een aparte thread die op hoge frequentie de mouse position pollt. Bij jouw oplossing tekent de UI thread op het bitmap, maar als het tekenen langer dan een paar miliseconden duurt krijg je dus gaten of schokken in je lijn.

  • Rotterdammertje
  • Registratie: Juni 2002
  • Laatst online: 28-03-2023
Je probleem-analyse klopt; als je een niet-onderbroken lijn wil, dan moet je het begin van de nieuwe lijn gelijk maken aan het eind van de vorige lijn. Je code doet precies het omgekeerde; het maakt het eind van de nieuwe lijn gelijk aan het begin van de oude lijn. Nu maakt dit in principe niet zo heel veel uit, maar het is duidelijker als je implementatie overeen komt met je redenatie. Overigens hoef je dit uiteraard alleen te doen als je daadwerkelijk lijnen aan het tekenen bent; nu wordt die code nog altijd uitgevoerd als de muis beweegt. Ook is het niet nodig om de X en Y locaties apart op te slaan. MouseEventArgs.Location geeft een Point object terug, en GraphicsPath verwacht een lijst van Point objecten. Je onMouseMove zou er dan ongeveer zo uit zien:

C#:
1
2
3
4
5
6
if (Tekenen)
{
    Point newLocation = e.Location;
    teken lijn van oldLocation naar newLocation;
    oldLocation = newLocation;
}

main = putStr (q ++ show q); q = "main = putStr (q ++ show q); q = "


  • JST94
  • Registratie: Juli 2009
  • Laatst online: 31-07 13:28
Rotterdammertje schreef op woensdag 11 september 2013 @ 10:06:
Je probleem-analyse klopt; als je een niet-onderbroken lijn wil, dan moet je het begin van de nieuwe lijn gelijk maken aan het eind van de vorige lijn. Je code doet precies het omgekeerde; het maakt het eind van de nieuwe lijn gelijk aan het begin van de oude lijn. Nu maakt dit in principe niet zo heel veel uit, maar het is duidelijker als je implementatie overeen komt met je redenatie. Overigens hoef je dit uiteraard alleen te doen als je daadwerkelijk lijnen aan het tekenen bent; nu wordt die code nog altijd uitgevoerd als de muis beweegt. Ook is het niet nodig om de X en Y locaties apart op te slaan. MouseEventArgs.Location geeft een Point object terug, en GraphicsPath verwacht een lijst van Point objecten. Je onMouseMove zou er dan ongeveer zo uit zien:

C#:
1
2
3
4
5
6
if (Tekenen)
{
    Point newLocation = e.Location;
    teken lijn van oldLocation naar newLocation;
    oldLocation = newLocation;
}
Dit is hetgene wat ik nu in mijn MouseMove event heb staan.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
        private void pB_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                Point oldLocation = e.Location;
                Point newLocation = e.Location;

                Graphics G = Graphics.FromImage(image1);
                Pen pen = new Pen(colorPen, thickLine);
                GraphicsPath Path = new GraphicsPath(
                    new Point[]
                    {
                        new Point(oldLocation.X, oldLocation.Y),
                        new Point(newLocation.X, newLocation.Y)
                    },
                    new byte[]
                    {
                        (byte)PathPointType.Start,
                        (byte)PathPointType.Line
                    });

                G.DrawPath(pen,Path);
                G.Save();
                pB.Image = image1;

                oldLocation = newLocation;
            }
        }


Ik dacht eerst dat hij misschien iets fout deed met het laden van de bitmap. Dus ter controle had ik even de achtergrondkleur van mijn image veranderd. Deze laad hij in ieder geval goed in de Picturebox.

In de bovenstaande code gaat echter nog iets fout, hij tekent nog steeds niet de lijn. Alleen ik kom er maar niet achter waarom, vandaag wat navraag gedaan bij de leraar en hij zei dat ik op de goede weg was en moest blijven proberen.

De code geeft ook geen foutmeldingen, dus ik kan er zo ook niet achter komen wat hier nou fout staat in de code. Kunnen jullie misschien zien waar het aan ligt, of wat er fout aan is?

  • DonKui
  • Registratie: November 2007
  • Laatst online: 11-05-2022
Misschien ligt het aan mij maar moet
C#:
1
Point oldLocation = e.Location;

daar dus niet staan?

Wat je nu doet is dat je de twee variabelen die je gebruikt om een lijn te trekken hetzelfde zijn

[ Voor 34% gewijzigd door DonKui op 11-09-2013 17:26 ]


Verwijderd

Ik vind de code op regel 5 behoorlijk verdacht.

Als C# variable scope hetzelfde werkt als in C++ klopt de scope van oldLocation ook niet. oldLocation hoort een member of global variable te zijn, correct? Met Point oldLocation declareer je een nieuwe variabele met die naam in de huidige scope.

  • JST94
  • Registratie: Juli 2009
  • Laatst online: 31-07 13:28
Verwijderd schreef op woensdag 11 september 2013 @ 17:34:
Ik vind de code op regel 5 behoorlijk verdacht.

Als C# variable scope hetzelfde werkt als in C++ klopt de scope van oldLocation ook niet. oldLocation hoort een member of global variable te zijn, correct? Met Point oldLocation declareer je een nieuwe variabele met die naam in de huidige scope.
Het tekenprobleem is ondertussen opgelost. Ik kwam er op een of andere manier achter dat er iets mis was met mijn MouseMove event. Ik had hem verwijderd en opnieuw aangemaakt.

Deze code werkt nu:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
        private void pB_MouseMove(object sender, MouseEventArgs e)
        {
            if (Draw)
            {

                newLocation = e.Location;

                G = Graphics.FromImage(image1);
                Pen pen = new Pen(colorPen, thickLine);
                GraphicsPath Path = new GraphicsPath(
                    new Point[]
                    {
                        new Point(oldLocation.X, oldLocation.Y),
                        new Point(newLocation.X, newLocation.Y)
                    },
                    new byte[]
                    {
                        (byte)PathPointType.Start,
                        (byte)PathPointType.Line
                    });

                G.SmoothingMode = SmoothingMode.AntiAlias;
                G.DrawPath(pen, Path);
                G.Save();
                pB.Image = image1;

                oldLocation = newLocation;
            }
        }


Ik heb de twee Points bovenaan gedeclareerd. Bij het controleren of Draw true is vul ik oldLocation met de waardes. Vanaf daar begin hij met tekenen, als je vervolgens gaat slepen word oldLocation verwisselt met new Location.

Bedankt voor jullie hulp ! _/-\o_

--
UPDATE

Ik ben op een nieuw probleem gestuit. Het opslaan van een een image. Het opslaan doet mijn programmaatje gewoon. Alleen op een beetje een aparte manier. Als ik op 'Opslaan' druk krijg ik het schermpje te zien waar ik het kan opslaan. Vervolgens voer ik de bestand naam in en druk ik op 'Opslaan'. Dan krijg ik opnieuw het schermpje te zien. Alleen dan staat er in de bestand naam het pad naar de afbeelding toe. Dus bijvoorbeeld: C:\Users\Ik\Afbeeldingen\Plaatje1. Als ik dan op opslaan druk dan slaat hij de afbeelding op. Ik heb alleen geen idee hoe dit komt.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        // Opslaan
        private void btnSave_Click(object sender, EventArgs e)
        {
            SaveFileDialog Opslaan = new SaveFileDialog();
            Opslaan.Filter = "Image Files(*.jpg; *.jpeg; *.gif; *.bmp)|*.jpg; *.jpeg; *.gif; *.bmp";
            Opslaan.Title = "Save an Image File";
            Opslaan.FilterIndex = 1;
            Opslaan.ShowDialog();

            if (Opslaan.ShowDialog() == DialogResult.OK)
            {
                image1.Save(Opslaan.FileName);
            }
        }


Enig idee waar dit aan kan liggen? Heb zelf al wat staan rommelen met de code maar ik kom er maar niet achter wat er nou fout is of of er iets teveel/teweinig instaat. :(

--
UPDATE 2

Na wat gerommel is het toch gelukt. Het weghalen van Opslaan.ShowDialog() haalde het probleem weg. Waarom die weg moest, geen idee haha.

[ Voor 27% gewijzigd door JST94 op 11-09-2013 22:20 ]


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Omdat je 'm een regel verderop wéér aanroept :? Je deed 2x showdialog ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • JST94
  • Registratie: Juli 2009
  • Laatst online: 31-07 13:28
RobIII schreef op woensdag 11 september 2013 @ 22:36:
Omdat je 'm een regel verderop wéér aanroept :? Je deed 2x showdialog ;)
Ahha, zo zit dat dus. Dankjewel :)

In deze opdracht moet ik ook het plaatje kunnen vergroten en verkleinen. Maar dat lukt me niet, je kan niet simpelweg een bitmap zijn grote aanpassen. Enig idee hoe ik hier aan moet beginnen? Aangezien ik maar geen uitkomst weet te vinden.

  • roboreaper
  • Registratie: Juli 2011
  • Laatst online: 01-11 22:47

roboreaper

Collecting your robots

wat wil je dan precies doen? je picture box vergroten zodat je plaatje meeschaalt of een selectie vergroten

  • JST94
  • Registratie: Juli 2009
  • Laatst online: 31-07 13:28
roboreaper schreef op donderdag 12 september 2013 @ 09:26:
wat wil je dan precies doen? je picture box vergroten zodat je plaatje meeschaalt of een selectie vergroten
Het gene wat moet gebeuren is dat het plaatje in de Picturebox groter word. Alleen het plaatje word geladen in een bitmap. Ik heb nu dus geen enkel probleem van hoe ik de grote er dan van aanpas.

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Je mag zelf ook wel wat meer moeite doen om het antwoord te vinden, ik vind met een simpele query op google genoeg informatie https://www.google.nl/sea...&sourceid=chrome&ie=UTF-8

“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.”

Pagina: 1