none
Grafik animieren RRS feed

  • Frage

  • Hallo an allen.

    Folgender Code verkleinert ein Rechteck bzw. animiert von außen nach innen.

    Wie kann ich aber erreichen, dass es andersrum animiert wird. Also von kleinen bis großen Rechteck - von innen nach außen - vergrößert wird?

    #pragma once
    
    namespace Forms_GraphicsDemo_1_timer {
    
    	using namespace System;
    	using namespace System::ComponentModel;
    	using namespace System::Collections;
    	using namespace System::Windows::Forms;
    	using namespace System::Data;
    	using namespace System::Drawing;
    
    	/// <summary>
    	/// Zusammenfassung für MyForm
    	/// </summary>
    	public ref class MyForm : public System::Windows::Forms::Form
    	{
    	public:
    		MyForm(void)
    		{
    			InitializeComponent();
    			
    
    			//aufrufe auf 0 setzen
    
    			aufrufe = 0;
    
    			//den Client-Bereich beschaffen
    
    			bereich = ClientRectangle;
    
    			
    			//
    			//TODO: Konstruktorcode hier hinzufügen.
    			//
    		}
    
    	protected:
    		/// <summary>
    		/// Verwendete Ressourcen bereinigen.
    		/// </summary>
    		~MyForm()
    		{
    			if (components)
    			{
    				delete components;
    			}
    		}
    
    		//ein eigenes Attribut zum Mitzählen der Aufrufe    
    
    		//und eins für die Größe des Zeichenbereichs
    
    	private:          
    
    		Int32 aufrufe;
    
    		Rectangle bereich;
    
    
    	private: System::Windows::Forms::Button^  buttonBeenden;
    	private: System::Windows::Forms::Timer^  timer1;
    	protected:
    
    
    	private: System::ComponentModel::IContainer^  components;
    
    	protected:
    
    	private:
    		/// <summary>
    		/// Erforderliche Designervariable.
    		/// </summary>
    
    
    #pragma region Windows Form Designer generated code
    		/// <summary>
    		/// Erforderliche Methode für die Designerunterstützung.
    		/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
    		/// </summary>
    		void InitializeComponent(void)
    		{
    			this->components = (gcnew System::ComponentModel::Container());
    			this->buttonBeenden = (gcnew System::Windows::Forms::Button());
    			this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
    			this->SuspendLayout();
    			// 
    			// buttonBeenden
    			// 
    			this->buttonBeenden->Location = System::Drawing::Point(197, 12);
    			this->buttonBeenden->Name = L"buttonBeenden";
    			this->buttonBeenden->Size = System::Drawing::Size(75, 23);
    			this->buttonBeenden->TabIndex = 0;
    			this->buttonBeenden->Text = L"Beenden";
    			this->buttonBeenden->UseVisualStyleBackColor = true;
    			this->buttonBeenden->Click += gcnew System::EventHandler(this, &MyForm::buttonBeenden_Click);
    			// 
    			// timer1
    			// 
    			this->timer1->Tick += gcnew System::EventHandler(this, &MyForm::timer1_Tick);
    			// 
    			// MyForm
    			// 
    			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
    			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    			this->ClientSize = System::Drawing::Size(284, 261);
    			this->Controls->Add(this->buttonBeenden);
    			this->Name = L"MyForm";
    			this->Text = L"MyForm";
    			this->WindowState = System::Windows::Forms::FormWindowState::Maximized;
    			this->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &MyForm::MyForm_Paint);
    			this->ResumeLayout(false);
    
    		}
    #pragma endregion
    	private: System::Void buttonBeenden_Click(System::Object^  sender, System::EventArgs^  e) {
    		Close();
    	}
    
    	private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
    		
    		//der Timer wurd alle 100 ms aufgerufen und zählt über ein 
    		//Attribut aufrufe mit, wie oft er bereits ausgeführt wurde
    
    		//die Zeichenfläche beschaffen
    
    		Graphics ^zeichenflaeche;
    
    		zeichenflaeche = this->CreateGraphics();
    
    		//einen schwarzen Stift erzeugen
    
    		Pen ^stift = gcnew Pen(Color::Black);
    
    		//die Zeichenfläche löschen
    
    		//das geschieht jetzt vor dem Zeichnen, damit die Grafik einen Moment zu sehen ist
    
    		zeichenflaeche->Clear(BackColor);
    
    		//wenn aufrufe kleiner ist als 22, wird das Rechteck gezeichnet
    
    		if (aufrufe < 22) {
    
    			//jeweils 10 von der Breite und Höhe abziehen
    
    			//bereich ist jetzt ein Attribut der Klasse und wird im Konstruktor gesetzt
    
    			bereich.Width = bereich.Width - 10;
    
    			bereich.Height = bereich.Height - 10;
    
    			//den Startpunkt setzen
    
    			bereich.Location = Point(bereich.Location.X + 5, bereich.Location.Y + 5);
    
    			//das Rechteck zeichnen
    
    			zeichenflaeche->DrawRectangle(stift, bereich);
    
    			//aufrufe erhöhen
    
    			aufrufe++;
    					
    		}
    		
    	}
    
    	private: System::Void MyForm_Paint(System::Object^  sender, System::Windows::Forms::PaintEventArgs^  e) {
    
    		//den Timer starten
    
    		timer1->Enabled = true;
    
    	}
    };
    }
    
    
    

    Für jede Hilfe bin ich dankbar.

    Dienstag, 18. November 2014 00:31

Antworten

  • Hallo,
    ich habe dein Projekt mal anhand meiner oben geschriebenen Änderungen angepasst. Du findest es hier.

    Zunächst habe ich einige Variablen aus der Klasse gelöscht, darunter zeichenflaeche und groesse. Des weiteren habe ich eine Funktion erstellt, die die Figur nach den Vorgaben auf ein Graphics-Objekt in einer bestimmten Größe zeichnet. Diese heißt ZeichneFigur.

    Beim Laden der Form wird nun entsprechend kein Graphics-Objekt mehr erzeugt, sondern stattdessen das Paint-Event des Panels abonniert. So wird sichergestellt, das die Form beim Verschieben usw. auch alles richtig neu zeichnet.

    Nun muss das Zeichnen als in das Paint-Event ausgelagert werden. Hier muss nun zunächst unterschieden werden, ob die Figur gelöscht, gezeichnet oder animiert werden soll. Dazu habe ich eine Variable animationsStatus hinzugefügt:

    private: enum Status
    {
    	Geloescht,
    	Animiert,
    	Statisch
    };
    Status status;

    Je nachdem was nun gesetzt wird, wird die Figur im Paint-Event gezeichnet/gelöscht. Das Setzen kann beispielsweise so aussehen:

    this->status = Status::Geloescht;
    panel1->Invalidate();//Panel neu zeichnen

    Im Eventhandler von Paint wird nun zwischen den 3 Stati unterschieden und entsprechend die Figur neu gezeichnet.

    Den Rest habe ich im Code kommentiert. Wenn sich weitere Fragen ergeben, poste diese einfach.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert newbie9854 Donnerstag, 20. November 2014 00:36
    Mittwoch, 19. November 2014 15:31
  • Der Timer wird im Click-Eventhandler des Buttons gestartet, nicht im Tick-Event des Timers. Dein Code müsste in etwa so aussehen:

    //wieder in die Form gelegt, um die Größe nicht ständig neu ermitteln zu müssen.
    Int32 ausgangsGroesse = 0;
    System::Void buttonAnimation_Click(System::Object^  sender, System::EventArgs^  e) {
    	kleiner = false;//Kleiner oder größer werdend?
    	switch (trackBar1->Value) {
    	case 1:
    		ausgangsGroesse = 125;
    		break;
    	case 2:
    		ausgangsGroesse = 100;
    		break;
    	case 3:
    		ausgangsGroesse = 75;
    		break;
    	}
    	position = ausgangsGroesse;
    
    	//Timer starten/stoppen mit dem selben Button
    	if (timer1->Enabled)//läuft der Timer bereits?
    	{
    		zaehler = Convert::ToInt32(numericUpDownWiederholungen->Value);//Zähler zurück setzen
    		timer1->Stop();//Timer anhalten
    	}
    	else
    		timer1->Start();//Timer starten
    }
    System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
    
    	if (kleiner)
    		position--;
    	else
    		position++;
    
    	if (position  == ausgangsGroesse)
    		timer1->Stop();//Timer anhalten, wenn Ausgangsgröße wieder erreicht wurde
    
    	//Wenn die Figur die Minimal/Maximalgröße erreicht hat, die Richtung der Größenveränderung ändern
    	if (position >= panel1->Width / 2)
    		kleiner = true;
    	if (position <= 1)
    		kleiner = false;
    
    	status = Status::Animiert;
    	panel1->Invalidate();//Panel neu zeichnen
    }

    Durch die Variable kleiner kannst du bestimmen in welche Richtung die Animation geht. Über den Fett markierten Teil im Tick-Eventhandler wird der Timer wieder angehalten, sobald die Ausgangsgröße erreicht wurde.

    Du solltest allerdings versuchen zu verstehen was dahinter steckt und es nicht nur blind kopieren.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert newbie9854 Donnerstag, 20. November 2014 00:36
    Mittwoch, 19. November 2014 18:43
  • Hallo,

    ich habe jetzt auch mal ein wenig "rumgespielt":

    Form_Spielerei

    Das Ganze könnte noch einigen Feinschliff vertragen... aber sehr viel Zeit konnte ich nicht erübrigen, da in Familienangelegenheiten unterwegs.

    Gruß Elmar

    • Als Antwort markiert newbie9854 Donnerstag, 20. November 2014 00:36
    Mittwoch, 19. November 2014 19:36

Alle Antworten

  • Hallo,
    momentan aktivierst du im Paint-Event einen Timer, in dem dan per CreateGraphics ein Objekt zum Zeichnen gehohlt wird. Dieses Verfahren kann jedoch schnell Fehler verursachen, weswegen ich dir zunächst empfehle den Timer anders um zu setzen.

    Übernehme das Zeichnen direkt im Paint-Event und beachte den Timer dort garnicht. Das Graphics-Objekt kannst du dir dort aus den EventArgs (e) hohlen. Im Tick-Event des Timers kannst du nun die Invalidate()-Methode aufrufen um die Form neu zeichnen zu lassen.
    Das Hochzählen der Aufrufe solltest du auch im Tick-Eventhandler durchführen, da die Form wesentlich öfter neu gezeichnet werden kann, als der Timer es verlangt. Das ist auch der Grund, warum man nicht mit jedem neuzeichnen etwas verändert, sondern immer in Abhängigkeit von einer Variablen. Das heißt, das du die Größe von bereich anhand von aufrufe festlegen kannst:

    bereich.Width = 200-aufrufe*10;
    bereich.Height = 200-aufrufe*10;
    bereich.Location = Point(aufrufe*5, aufrufe *5);
    Da mit der Zeit aufrufe immer größer wird, wird bereich immer kleiner. Um es nun größer werden zu lassen, lösche einfach das 200- aus dem Code heraus.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Dienstag, 18. November 2014 08:40
  • Koopakiller, danke für Deine Antwort.

    Ich verstehen aber nicht, wie ich Elemente (ohne Füllungen) - Kreise und Rechtecke Animation programmiere, damit diese von innen nach außen schrittweise vergrößert werden bis zum äußeren Rand des weißen Panels - Zeichenfläche. Und zwar angefangen von der Größe in der diese bereits gezeichnet sind. Danach sollen diese wieder von außen nach innen verkleinert werden, bis der Anfangsgröße.

    #pragma once namespace Forms_spielerei { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; /// <summary> /// Zusammenfassung für MyForm /// </summary> public ref class MyForm : public System::Windows::Forms::Form { public: MyForm(void) { InitializeComponent(); //zähler auf 0 setzen zaehler = 0; //aufrufe auf 0 setzen aufrufe = 0; //den Client-Bereich beschaffen bereich = panel1->ClientRectangle; } protected: /// <summary> /// Verwendete Ressourcen bereinigen. /// </summary> ~MyForm() { if (components) { delete components; } } private: Graphics ^zeichenflaeche; Color linienFarbe; Color hintergrundFarbe; Int32 zaehler; Int32 aufrufe; Rectangle bereich; Int32 groesse; /* Die Vereinbarung muss als static erfolgen. Andernfalls kann man dem Array keine Werte zuweisen. */ //für die Linienstile static array <Drawing2D::DashStyle> ^linienstil = { Drawing2D::DashStyle::Dash, Drawing2D::DashStyle::DashDot, Drawing2D::DashStyle::DashDotDot, Drawing2D::DashStyle::Dot, Drawing2D::DashStyle::Solid }; //für die Hintergrundmuster static array <Drawing2D::HatchStyle> ^fuellstil = { Drawing2D::HatchStyle::BackwardDiagonal, Drawing2D::HatchStyle::Cross, Drawing2D::HatchStyle::DottedGrid, Drawing2D::HatchStyle::ForwardDiagonal, Drawing2D::HatchStyle::Sphere, Drawing2D::HatchStyle::Vertical, Drawing2D::HatchStyle::Wave, Drawing2D::HatchStyle::ZigZag }; private: System::Windows::Forms::Panel^ panel1; private: System::Windows::Forms::GroupBox^ groupBox2; private: System::Windows::Forms::GroupBox^ groupBox1; private: System::Windows::Forms::Label^ label3; private: System::Windows::Forms::Label^ label2; private: System::Windows::Forms::ListBox^ listBoxLinieStil; private: System::Windows::Forms::Label^ label1; private: System::Windows::Forms::NumericUpDown^ numericUpDownLinieStaerke; private: System::Windows::Forms::RadioButton^ radioButtonHintergrundMuster; private: System::Windows::Forms::RadioButton^ radioButtonHintergrundFarbe; private: System::Windows::Forms::RadioButton^ radioButtonHintergrundOhne; private: System::Windows::Forms::ListBox^ listBoxHintergrundMuster; private: System::Windows::Forms::Label^ label5; private: System::Windows::Forms::Label^ label4; private: System::Windows::Forms::GroupBox^ groupBox3; private: System::Windows::Forms::RadioButton^ radioButtonLinie; private: System::Windows::Forms::RadioButton^ radioButtonKreis; private: System::Windows::Forms::RadioButton^ radioButtonRechteck; private: System::Windows::Forms::TrackBar^ trackBar1; private: System::Windows::Forms::Button^ buttonStart; private: System::Windows::Forms::Button^ buttonLoeschen; private: System::Windows::Forms::Button^ buttonBeenden; private: System::Windows::Forms::Button^ buttonLinieFarbe; private: System::Windows::Forms::Panel^ panelLinieFarbeVorschau; private: System::Windows::Forms::ColorDialog^ colorDialog1; private: System::Windows::Forms::Button^ buttonHintergrundFarbe; private: System::Windows::Forms::Panel^ panelHintergrundFarbeVorschau; private: System::Windows::Forms::Label^ label6; private: System::Windows::Forms::Label^ label7; private: System::Windows::Forms::Button^ buttonAnimation; private: System::Windows::Forms::NumericUpDown^ numericUpDownWiederholungen; private: System::Windows::Forms::NumericUpDown^ numericUpDownDauer; private: System::Windows::Forms::Timer^ timer1; private: System::ComponentModel::IContainer^ components; protected: protected: private: /// <summary> /// Erforderliche Designervariable. /// </summary> #pragma region Windows Form Designer generated code /// <summary> /// Erforderliche Methode für die Designerunterstützung. /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. /// </summary> void InitializeComponent(void) { //##### Designer Code ausgeschnitten ######## } #pragma endregion private: System::Void buttonBeenden_Click(System::Object^ sender, System::EventArgs^ e) { Close(); } private: System::Void MyForm_Load(System::Object^ sender, System::EventArgs^ e) { //die Linienfarbe auf Schwarz setzen linienFarbe = Color::Black; //und auch die Hintergrundfarbe hintergrundFarbe = Color::Black; //die Einträge für die Linienstile erzeugen for each (Drawing2D::DashStyle element in linienstil) listBoxLinieStil->Items->Add(""); //und für die Hintergrundmuster for each (Drawing2D::HatchStyle element in fuellstil) listBoxHintergrundMuster->Items->Add(""); //einen Handle auf die Zeichenfläche des Panels setzen //zeichenflaeche ist als Attribut der Klasse Form1 vereinbart zeichenflaeche = panel1->CreateGraphics(); } private: System::Void buttonLoeschen_Click(System::Object^ sender, System::EventArgs^ e) { //die Zeichenfläche löschen zeichenflaeche->Clear(panel1->BackColor); } private: System::Void buttonStart_Click(System::Object^ sender, System::EventArgs^ e) { //eine lokale Variable für die Größe //Int32 groesse; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //einen schwarzen Stift erzeugen Pen ^stift = gcnew Pen(linienFarbe); //einen schwarzen Pinsel erzeugen SolidBrush ^pinsel = gcnew SolidBrush(hintergrundFarbe); //die Dicke des Stiftes setzen stift->Width = Convert::ToSingle(numericUpDownLinieStaerke->Value); //den Linienstil setzen, wenn ein Wert gewählt wurde if (listBoxLinieStil->SelectedIndex >= 0) stift->DashStyle = linienstil[listBoxLinieStil->SelectedIndex]; //die Größe der Figur ermitteln switch (trackBar1->Value) { case 1: groesse = 125; break; case 2: groesse = 100; break; case 3: groesse = 75; break; } //Figur ermitteln //beim Kreis und beim Rechteck auch die Füllung überprüfen if (radioButtonKreis->Checked == true) { if (radioButtonHintergrundOhne->Checked == true) zeichenflaeche->DrawEllipse(stift, panel1->ClientRectangle.Left + groesse, panel1->ClientRectangle.Top + groesse, panel1->ClientRectangle.Width - (groesse * 2), panel1->ClientRectangle.Height - (groesse * 2)); if (radioButtonHintergrundFarbe->Checked == true) zeichenflaeche->FillEllipse(pinsel, panel1->ClientRectangle.Left + groesse, panel1->ClientRectangle.Top + groesse, panel1->ClientRectangle.Width - (groesse * 2), panel1->ClientRectangle.Height - (groesse * 2)); //soll mit Muster gezeichnet werden und ist ein Muster ausgewählt? if (radioButtonHintergrundMuster->Checked == true && listBoxHintergrundMuster->SelectedIndex >= 0) { //einen neuen Pinsel für das Muster erzeugen //die Vordergrundfarbe kommt vom Stift, der Hintergrund ist immer weiß Drawing2D::HatchBrush ^musterPinsel = gcnew Drawing2D::HatchBrush(fuellstil[listBoxHintergrundMuster->SelectedIndex], stift->Color, Color::White); zeichenflaeche->FillEllipse(musterPinsel, panel1->ClientRectangle.Left + groesse, panel1->ClientRectangle.Top + groesse, panel1->ClientRectangle.Width - (groesse * 2), panel1->ClientRectangle.Height - (groesse * 2)); delete musterPinsel; } } if (radioButtonRechteck->Checked == true) { if (radioButtonHintergrundOhne->Checked == true) zeichenflaeche->DrawRectangle(stift, panel1->ClientRectangle.Left + groesse, panel1->ClientRectangle.Top + groesse, panel1->ClientRectangle.Width - (groesse * 2), panel1->ClientRectangle.Height - (groesse * 2)); if (radioButtonHintergrundFarbe->Checked == true) zeichenflaeche->FillRectangle(pinsel, panel1->ClientRectangle.Left + groesse, panel1->ClientRectangle.Top + groesse, panel1->ClientRectangle.Width - (groesse * 2), panel1->ClientRectangle.Height - (groesse * 2)); //soll mit Muster gezeichnet werden und ist ein Muster ausgewählt? if (radioButtonHintergrundMuster->Checked == true && listBoxHintergrundMuster->SelectedIndex >= 0) { //einen neuen Pinsel für das Muster erzeugen //die Vordergrundfarbe kommt vom Stift, der Hintergrund ist immer weiß Drawing2D::HatchBrush ^musterPinsel = gcnew Drawing2D::HatchBrush(fuellstil[listBoxHintergrundMuster->SelectedIndex], stift->Color, Color::White); zeichenflaeche->FillRectangle(musterPinsel, panel1->ClientRectangle.Left + groesse, panel1->ClientRectangle.Top + groesse, panel1->ClientRectangle.Width - (groesse * 2), panel1->ClientRectangle.Height - (groesse * 2)); delete musterPinsel; } } if (radioButtonLinie->Checked == true) zeichenflaeche->DrawLine(stift, panel1->ClientRectangle.Left + groesse, panel1->ClientRectangle.Height / 2, panel1->ClientRectangle.Width - groesse, panel1->ClientRectangle.Height / 2); //Stift und Pinsel löschen delete stift; delete pinsel; } private: System::Void buttonLinieFarbe_Click(System::Object^ sender, System::EventArgs^ e) { //den Dialog zur Farbauswahl anzeigen if (colorDialog1->ShowDialog() == Windows::Forms::DialogResult::OK) { //die Hintergrundfarbe für das Panel auf die ausgewählte Farbe setzen panelLinieFarbeVorschau->BackColor = colorDialog1->Color; //und die Linienfarbe //linienFarbe ist ein Attribut der Klasse Form1 linienFarbe = colorDialog1->Color; } } private: System::Void buttonHintergrundFarbe_Click(System::Object^ sender, System::EventArgs^ e) { //den Dialog zur Farbauswahl anzeigen if (colorDialog1->ShowDialog() == Windows::Forms::DialogResult::OK) { //die Hintergrundfarbe für das Panel auf die ausgewählte Farbe setzen panelHintergrundFarbeVorschau->BackColor = colorDialog1->Color; //und die eigentliche Hintergrundfarbe //hintergrundFarbe ist ein Attribut der Klasse Form1 hintergrundFarbe = colorDialog1->Color; //die Auswahl Farbe aktivieren radioButtonHintergrundFarbe->Checked = true; } } private: System::Void listBoxLinieStil_DrawItem(System::Object^ sender, System::Windows::Forms::DrawItemEventArgs^ e) { //eine lokale Variable für die Berechnung der Mitte Int32 Y; //ein neuer lokaler Stift Pen ^boxStift = gcnew Pen(Color::Black); //die Mitte berechnen Y = (e->Bounds.Top + e->Bounds.Bottom) / 2; //den Hintergrund zeichnen e->DrawBackground(); //und die Linie boxStift->DashStyle = linienstil[e->Index]; e->Graphics->DrawLine(boxStift, e->Bounds.Left + 1, Y, e->Bounds.Right - 1, Y); //den Stift löschen delete boxStift; } private: System::Void listBoxHintergrundMuster_DrawItem(System::Object^ sender, System::Windows::Forms::DrawItemEventArgs^ e) { //ein neuer lokaler Pinsel für das Muster Drawing2D::HatchBrush ^boxPinsel = gcnew Drawing2D::HatchBrush(fuellstil[e->Index], Color::Black, Color::White); //den Hintergrund zeichnen e->DrawBackground(); //und das Rechteck e->Graphics->FillRectangle(boxPinsel, e->Bounds.Left + 1, e->Bounds.Top + 1, e->Bounds.Width - 1, e->Bounds.Height - 1); //den Pinsel löschen delete boxPinsel; } private: System::Void numericUpDownDauer_ValueChanged(System::Object^ sender, System::EventArgs^ e) { timer1->Interval = Convert::ToInt32(numericUpDownDauer->Value) * 100; } private: System::Void numericUpDownWiederholungen_ValueChanged(System::Object^ sender, System::EventArgs^ e) { zaehler = Convert::ToInt32(numericUpDownWiederholungen->Value); } };

    }

    Die Animation soll über die Schaltfläche gestartet werden.

    Danke sehr.



    • Bearbeitet newbie9854 Dienstag, 18. November 2014 13:45
    Dienstag, 18. November 2014 13:36
  • Hat jemand Tipps, die mich weiter bringen?
    Dienstag, 18. November 2014 21:32
  • Hallo,

    da Du den Code verkürzt hast, wäre es etwas mühselig, die vielen Optionen erst wieder manuell zu erstellen.

    Wenn Du das Projekt als Download auf OneDrive bereitstellen könntest, wäre es leichter möglich, Dir den Weg zu zeigen.

    Gruß Elmar

    Mittwoch, 19. November 2014 06:02
  • Hallo,

    danke für Deine Antwort und Hilfe.

    Hier ist das Project:

    https://onedrive.live.com/redir?resid=FEC0CE14F1FE110B%21105

    MfG

    Mittwoch, 19. November 2014 09:56
  • Hallo,
    ich habe dein Projekt mal anhand meiner oben geschriebenen Änderungen angepasst. Du findest es hier.

    Zunächst habe ich einige Variablen aus der Klasse gelöscht, darunter zeichenflaeche und groesse. Des weiteren habe ich eine Funktion erstellt, die die Figur nach den Vorgaben auf ein Graphics-Objekt in einer bestimmten Größe zeichnet. Diese heißt ZeichneFigur.

    Beim Laden der Form wird nun entsprechend kein Graphics-Objekt mehr erzeugt, sondern stattdessen das Paint-Event des Panels abonniert. So wird sichergestellt, das die Form beim Verschieben usw. auch alles richtig neu zeichnet.

    Nun muss das Zeichnen als in das Paint-Event ausgelagert werden. Hier muss nun zunächst unterschieden werden, ob die Figur gelöscht, gezeichnet oder animiert werden soll. Dazu habe ich eine Variable animationsStatus hinzugefügt:

    private: enum Status
    {
    	Geloescht,
    	Animiert,
    	Statisch
    };
    Status status;

    Je nachdem was nun gesetzt wird, wird die Figur im Paint-Event gezeichnet/gelöscht. Das Setzen kann beispielsweise so aussehen:

    this->status = Status::Geloescht;
    panel1->Invalidate();//Panel neu zeichnen

    Im Eventhandler von Paint wird nun zwischen den 3 Stati unterschieden und entsprechend die Figur neu gezeichnet.

    Den Rest habe ich im Code kommentiert. Wenn sich weitere Fragen ergeben, poste diese einfach.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert newbie9854 Donnerstag, 20. November 2014 00:36
    Mittwoch, 19. November 2014 15:31
  • Koopakiller,

    danke für Deine Hilfe und Mühe!

    Leider funktioniert aber die Funktion für die Größenermittlung nicht korrekt.

    Es startet nähmlich von max. Größe des Panels und wird immer kleiner... - also von außen nach innen.

    Es muss zunächst z.B. Kreis gezeichnet werden - in einer der drei Größen.

    Danach soll durch den Klick die Animation ab der Größe des Kreises und co. von innen nach außen gestartet werden.

    Wenn die max. Größe des Panels erreicht wurde, soll es wieder wieder kleiner werden bis Anfangsgröße.

    Könntest Du es noch bitte ändern?

    Danke nochmal für Deine schon geleistete Mühe.



    • Bearbeitet newbie9854 Mittwoch, 19. November 2014 16:47
    Mittwoch, 19. November 2014 16:46
  • Hallo,
    dann setze beim Starten des Timers position entsprechend der ausgewählten Größe und halte den Timer im Tick-Event wieder an, wenn die Größe wieder erreicht wurde.

    Wie die Animation an sich funktioniert, siehst du in meinem Code. Der Rest ist nur Anpassen der verwendeten Parameter/Variablen.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Mittwoch, 19. November 2014 16:53
  • Hallo,

    habe im Timer dies:

    Int32 groesse = 0;
    		switch (trackBar1->Value) {
    		case 1:
    			groesse = 125;
    			break;
    		case 2:
    			groesse = 100;
    			break;
    		case 3:
    			groesse = 75;
    			break;
    		}
    		position = groesse;

    am anfang gesetzt, um richtige Anfangsgröße zu erreichen - hat auch "geklappt", aber jetzt funktioniert die Animation gar nicht mehr - in gar keine Richtung.

    Unter diesem Code im Timer ist natürlich noch Deine Code.

    Was ist der Grund?

    Könntest Du mir bitte noch kurzen Beispiel nennen?

    Danke




    • Bearbeitet newbie9854 Mittwoch, 19. November 2014 18:26
    Mittwoch, 19. November 2014 18:08
  • Der Timer wird im Click-Eventhandler des Buttons gestartet, nicht im Tick-Event des Timers. Dein Code müsste in etwa so aussehen:

    //wieder in die Form gelegt, um die Größe nicht ständig neu ermitteln zu müssen.
    Int32 ausgangsGroesse = 0;
    System::Void buttonAnimation_Click(System::Object^  sender, System::EventArgs^  e) {
    	kleiner = false;//Kleiner oder größer werdend?
    	switch (trackBar1->Value) {
    	case 1:
    		ausgangsGroesse = 125;
    		break;
    	case 2:
    		ausgangsGroesse = 100;
    		break;
    	case 3:
    		ausgangsGroesse = 75;
    		break;
    	}
    	position = ausgangsGroesse;
    
    	//Timer starten/stoppen mit dem selben Button
    	if (timer1->Enabled)//läuft der Timer bereits?
    	{
    		zaehler = Convert::ToInt32(numericUpDownWiederholungen->Value);//Zähler zurück setzen
    		timer1->Stop();//Timer anhalten
    	}
    	else
    		timer1->Start();//Timer starten
    }
    System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {
    
    	if (kleiner)
    		position--;
    	else
    		position++;
    
    	if (position  == ausgangsGroesse)
    		timer1->Stop();//Timer anhalten, wenn Ausgangsgröße wieder erreicht wurde
    
    	//Wenn die Figur die Minimal/Maximalgröße erreicht hat, die Richtung der Größenveränderung ändern
    	if (position >= panel1->Width / 2)
    		kleiner = true;
    	if (position <= 1)
    		kleiner = false;
    
    	status = Status::Animiert;
    	panel1->Invalidate();//Panel neu zeichnen
    }

    Durch die Variable kleiner kannst du bestimmen in welche Richtung die Animation geht. Über den Fett markierten Teil im Tick-Eventhandler wird der Timer wieder angehalten, sobald die Ausgangsgröße erreicht wurde.

    Du solltest allerdings versuchen zu verstehen was dahinter steckt und es nicht nur blind kopieren.


    Tom Lambert - C# MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    • Als Antwort markiert newbie9854 Donnerstag, 20. November 2014 00:36
    Mittwoch, 19. November 2014 18:43
  • Hallo,

    ich habe jetzt auch mal ein wenig "rumgespielt":

    Form_Spielerei

    Das Ganze könnte noch einigen Feinschliff vertragen... aber sehr viel Zeit konnte ich nicht erübrigen, da in Familienangelegenheiten unterwegs.

    Gruß Elmar

    • Als Antwort markiert newbie9854 Donnerstag, 20. November 2014 00:36
    Mittwoch, 19. November 2014 19:36
  • Danke

    Kleinigkeiten habe ich noch selbst angepasst.

    Ich werde mich in dieses Programm "reinsetzen" - ich will nähmlich lernen, und nicht schnell kopieren und die Aufgabe ist geschafft.

    Aber allein hätte ich es nicht geschafft.

    Danke für Deine Mühe und Hilfe.

    Mittwoch, 19. November 2014 19:51
  • Elmar Boye,

    danke auch für Deine Mühe.

    Ich werden auch von Deiner Variante ganz bestimmt was lernen.


    • Bearbeitet newbie9854 Mittwoch, 19. November 2014 20:42
    Mittwoch, 19. November 2014 20:22