Slideshow
-
Helfender Helfer schrieb:
Etwas verwirrend geschrieben dein Programmschen
ich hab mir mal die zeit genommen und dir was zusammen gebastelt.
Alles Übungssache; ich blicke da prima durch
Ist aber wirklich super nett von Dir, vielen Dank.So, zu Deinem Code. Ich habe ein bisschen gebraucht, verstehe aber alles (denke ich).
Ich probiere mal, das in mein bestehendes Programm zu integrieren; ist mir lieber, als deinen Code komplett zu übernehmen.Wenn sich der Ordnerinhalt nun ändert, wird aber die Wiedergabeliste gelöscht. D.h. die Slideshow würde wieder mit dem erten Bild beginnen; sehe ich das richtig? An dem Punkt würde ich dann wohl was ändern.
Du hast Dispose() nur überschrieben, um es mir zu zeigen, oder? Zumindest kann ich keine Verwendung im Code entdecken.
Ach so, eins noch. Du verwendest eine PictureBox statt meinem Panel. Gibt es dafür einen Grund? Performance?
Nochmals vielen Dank.
Will Dir aber nicht zuviel Arbeit machen (auch wenn Du das wohl ziemlich schnell geproggt bekommst).
-
PictureBox bringt viel mehr da er extra für solche dinge gemacht wurde und kein Panel
und Performence bringt es auch wie ich im taskmanager sehe bleibt er nur bei 12.000.
if (pictureBox1.Image != null) pictureBox1.Image.Dispose();
da hab ich es benutzt! Ganz am anfang ist doch das Image null und das muss man abfangen sonst gibts Fehler, da man keine Ressourcen freigeben kann wo nix ist.
Das der wieder von vorne beginnt ist besser, denn falls das nächste bild was du anzeigen willst wiedergeben willst weiß er nicht wo was ist. du könntest das natürlich auch umändern aber ich wollt dir nur ein bisschen code zeigen ^^ damit du ein bisschen die Richtung hast.
Und das du dein code benutzt ist auch gut denn wenn man es von anderen nur ganze zeit vorgaugelt bekommt lernt man selbst auch nix dabei.
mfg Helfender Helfer
-
this->lFileNames = gcnew System::Collections::Generic::List<System::String>(System::IO::Directory::GetFiles(this->folderBrowserDialog1->SelectedPath, L"*.jpg"));
bzw.
this->lFileNames = gcnew System::Collections::Generic::List<System::String^>(System::IO::Directory::GetFiles(this->folderBrowserDialog1->SelectedPath, L"*.jpg"));
Das funktioniert bei mir leider nicht so einfach. Eine Konvertierung von array in List bzw. String ist so nicht möglich.
Leider bekomme ich auch das Überschreiben von Dispose() nicht hin, weil bei mir die Syntax wohl komplett anders lauten muss.
Jetzt bekomme ich wohl doch zu spüren, dass ich im falschen Subforum bin *lach*
-
Dann mach ne schleife die das dann macht also:
List<String> list = new List<string>(); String[] allfiles = System.IO.Directory.GetFiles(this.folderBrowserDialog1.SelectedPath, "*.jpg"); foreach(String file in allfiles) { list.Add(file); }
und dein Dispose aufruf? Zeigmal wie du ihn aufrufst. Benutzt du ne PictureBox?
-
Mit der Schleife hab ich es auch gelöst. Ist halt nur immer unschön, unnötig zusätzliche Variablen zu brauchen; aber so groß ist das Array ja nicht.
So sieht's aus:
private: System::Void TimerEventProcessor(System::Object^ sender, System::Timers::ElapsedEventArgs^ e) { if (this->lFileNames->Count > 0) { this->tTimer->Stop(); this->pictureBox1->Image = System::Drawing::Image::FromFile(this->lFileNames[0]); this->lFileNames->Remove(lFileNames[0]); this->tTimer->Start(); } else { das Gleiche, nur wird halt zusätzlich die Liste neu gefüllt } }
So hab ich es versucht:
private: System::Void TimerEventProcessor(System::Object^ sender, System::Timers::ElapsedEventArgs^ e) { if (this->lFileNames->Count > 0) { this->tTimer->Stop(); this->pictureBox1->Dispose(); this->pictureBox1->Image = System::Drawing::Image::FromFile(this->lFileNames[0]); this->lFileNames->Remove(lFileNames[0]); this->tTimer->Start(); } else { das Gleiche, nur wird halt zusätzlich die Liste neu gefüllt } }
c:\users\marian\documents\visual studio 2005\projects\fotoslider\fotoslider\Form1.h(288) : error C2039: 'Dispose': Ist kein Element von 'System::Windows::Forms::PictureBox' c:\windows\microsoft.net\framework\v2.0.50727\system.windows.forms.dll: Siehe Deklaration von 'System::Windows::Forms::PictureBox' Sie sollten stattdessen den Destruktor, "~PictureBox", aufrufen.
Verstehe das nicht, weil er mir Dispose() ja sogar vorschlägt, wenn ich this->pictureBox1-> schreibe.
Bewundernswert, dass es bei Dir nur 12MB braucht
Ich mache gerade mal einen Testlauf (1000 Bilder, solange bis er abstürzt).
Der Bedarf steigt auf so ca. 250MB. Dann werden Ressourcen freigegeben und er fällt auf 40. Zwar gierig, aber es läuft konstant.
Mit was für Bildern hast Du es denn getestet? Die 10MegaPixel-Bilder aus meiner Spiegelreflex muss es schon verkraften
-
pictureBox1->Image->Dispose()
Helfender Helfer
-
Ach du solltest natürlich auch noch beachten das das Image am anfang null ist! also:
private: System::Void TimerEventProcessor(System::Object^ sender, System::Timers::ElapsedEventArgs^ e) { if (this->lFileNames->Count > 0) { this->tTimer->Stop(); if(this->pictureBox1->Image != null) this->pictureBox1->Image->Dispose(); this->pictureBox1->Image = System::Drawing::Image::FromFile(this->lFileNames[0]); this->lFileNames->Remove(lFileNames[0]); this->tTimer->Start(); } else { das Gleiche, nur wird halt zusätzlich die Liste neu gefüllt }
}
-
Ah sorry, hatte es jetzt nur mal auf die Schnelle hineingeschrieben, um die Fehlermeldung posten zu können.
Bei meinen ersten Versuchen hab' ich das "Image" mit drin gehabt
c:\users\marian\documents\visual studio 2005\projects\fotoslider\fotoslider\Form1.h(288) : error C2039: 'Dispose': Ist kein Element von 'System::Drawing::Image' c:\windows\microsoft.net\framework\v2.0.50727\system.drawing.dll: Siehe Deklaration von 'System::Drawing::Image' Sie sollten stattdessen den Destruktor, "~Image", aufrufen.
-
achso C++
mach ein
delete(this->pictureBox1->Image);
anstatt das
this->pictureBox1->Image->Dispose();
-
AHHHHHHHHHHHHHHH, ich halts nicht aus. Ich Volldepp
War so verzweifelt, dass ich Sachen wie ~this->pictureBox1->Image etc. versucht habe.
delete() ... es darf nicht wahr sein. Dabei hab' ich das sogar mal in einem Projekt zum Beenden desselbigen verwendet, bis ich dann irgendwann entdeckt habe, dass man das Formular über Close() beenden kann.Danke, jetzt verbraucht mein Programm ziemlich konstant 30MB bei 10MP-Dateien; das wird wohl die ungefähre Größe des entsprechenden Bitmaps sein.
Du hast meine Party echt gerettet, tausend Dank
-
Und da bin ich leider auch schon wieder
Nachdem nun alles inkl. Vollbildmodus und genügsamen Speichermanagement funktioniert und sich mein Projekt auf einem anderen Rechner auch zu einer lauffähigen Exe kompilieren ließ, habe ich nun ein dickes Problem hier.
Bewegt man in dem Moment des Bildwechsels ein anderes Fenster über die Picturebox, so stürzt mein Programm mit folgender Meldung ab:
************** Ausnahmetext **************
System.ArgumentException: Ungültiger Parameter.
bei System.Drawing.Image.get_Width()
bei System.Drawing.Image.get_Size()
bei System.Windows.Forms.PictureBox.ImageRectangleFromSizeMode(PictureBoxSizeMo
de mode)
bei System.Windows.Forms.PictureBox.get_ImageRectangle()
bei System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
bei System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
bei System.Windows.Forms.Control.WmPaint(Message& m)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)Mein Bild wird in der Mainform in einer Picturebox angezeigt. Ausgelöst wird der Bildwechsel durch ein Timerevent:
private: System::Void TimerEventProcessor(System::Object^ sender, System::Timers::ElapsedEventArgs^ e) { //Speicher vom alten Bild befreien delete(this->pictureBox1->Image); //Wenn die Dateinamenliste noch Einträge enthält... if (this->lFileNames->Count > 0) { this->tTimer->Stop(); //bRandom enthält den Bool für die zufällige Bildwiedergabe if (bRandom == true) { int x = this->lFileNames->Count; int y = this->random->Next(0, x); //Überprüfung, für den Fall, dass inzwischen ein Bild gelöscht wurde while ((this->lFileNames->Count > 0) && (System::IO::File::Exists(this->lFileNames[y]) == false)) { this->lFileNames->Remove(lFileNames[y]); x = this->lFileNames->Count; y = this->random->Next(0, x); } //Wenn die Dateinamenliste danach immer noch Einträge enthält... if (this->lFileNames->Count > 0) { this->pictureBox1->Image = System::Drawing::Image::FromFile(this->lFileNames[y]); this->lFileNames->Remove(lFileNames[y]); } } else { //Überprüfung, für den Fall, dass inzwischen ein Bild gelöscht wurde while ((this->lFileNames->Count > 0) && (System::IO::File::Exists(this->lFileNames[0]) == false)) { this->lFileNames->Remove(lFileNames[0]); } //Wenn die Dateinamenliste danach immer noch Einträge enthält... if (this->lFileNames->Count > 0) { this->pictureBox1->Image = System::Drawing::Image::FromFile(this->lFileNames[0]); this->lFileNames->Remove(lFileNames[0]); } } this->tTimer->Start(); } else { this->tTimer->Stop(); loadFileNames(); if (bRandom == true) { int x = this->lFileNames->Count; int y = this->random->Next(0, x); this->pictureBox1->Image = System::Drawing::Image::FromFile(this->lFileNames[y]); this->lFileNames->Remove(lFileNames[y]); } else { this->pictureBox1->Image = System::Drawing::Image::FromFile(this->lFileNames[0]); this->lFileNames->Remove(lFileNames[0]); } this->tTimer->Start(); } }
Der Absturz erfolgt auch, wenn man die Fenstergröße während des Bildwechsel verändert.
Ich würde es mit einer try-Anweisung versuchen, hab aber keine Ahnung, wie das entsprechende catch lauten muss
-
Ich habe es in meiner showPicture-Methode einfach mal so probiert:
private: System::Void showPicture(int x) { try { this->pictureBox1->Image = System::Drawing::Image::FromFile(this->lFileNames[x]); this->lFileNames->Remove(lFileNames[x]); } catch(...) {} }
Der Absturz erfolgt aber nach wie vor. Wenn ich mir die Fehlermeldung so anschaue, könnte es auch an der Picturebox ansich, bzw dem SizeMode liegen.
this->pictureBox1->SizeMode = System::Windows::Forms::PictureBoxSizeMode::Zoom;
Hat jemand eine Idee?
-
mach doch mal den fehler im debug modus und sag wos hängt ^^
mfg Helfender Helfer
-
Eine nicht behandelte Ausnahme des Typs "System.ArgumentException" ist in System.Drawing.dll aufgetreten. Zusätzliche Informationen: Ungültiger Parameter.
und er schickt mich zum return meiner main.
In der "Aufrufliste" steht ein kleiner gelber Pfeil bei System.Drawing.dll!System.Drawing.Image.Width.get() + 0x54 Bytes.
Auf meinem PC (also mit installiertem VS) tritt der Fehler aber nur auf, wenn man die Fenstergröße (damit auch die Picturebox) während des Bildwechsels ändert.
Ein Rumhantieren mit anderen Dialogfenstern stört ihn (im Gegensatz zu dritten PCs ohne VS) nicht.Ich überlege gerade, ob es eventuell hilft, den Fenstermodus beim Laden eines Bilder auf "nicht veränderbar" zu setzen.
Jedoch wäre das nur die Lösung für das Problem an meinem PC. Auf dritten Rechner reicht es wie gesagt schon, wenn man zum Zeitpunkt des Bildwechsel ein fremdes Dialogfenster über meiner Hauptform mit der Picturebox bewegt. Da hilft meine Idee natürlich nicht weiter.Nachtrag: Meine Idee funktioniert leider nicht.
-
Eines haben schlaflose Nächte für sich. Wenn man nicht einschläft denkt man über allen möglichen Kram nach.
Mein Programm verabschiedet sich, da ich vor dem Laden des neuen Bildes das alte per delete() lösche. Die Resize-Funktion des Fensters scheint das wohl nicht zu mögen, da ein Bild, dessen Größe es verändern will, auf einmal nicht mehr da ist.
Daher kam es auch auf meinem Win2000 System nicht zum Absturz. Dort wird die Änderung der Fenstergröße nämlich erst übernommen, wenn man die Maus loslässt.
WinXP und Vista machen das ja quasi just in time.Das Ändern der Fenstereigenschaft auf Fixed ist hilft aber leider nur auf den ersten Blick. Maximiert man nämlich genau während des Bildwechsel, kommt es wieder zum gleichen Problem.
Ich müsste in meiner Methode eine Überprüfung haben, ob die Fenstergröße aktuell verändert wird. Falls ja, soll er solange mit dem Bildwechsel warten.
-
Stop den Timer für den Bildwechsel im ResizeBegin Event und starte ihn wieder im ResizeEnd Event.
Z. B. so:
private: System::Void Form1_ResizeBegin(System::Object^ sender, System::EventArgs^ e) { this->timer1->Stop(); } private: System::Void Form1_ResizeEnd(System::Object^ sender, System::EventArgs^ e) { this->timer1->Start(); }
-
Danke, das funktioniert gut.
Kann mir nochjemand sagen, welches Events durch Klicken der Maximieren/Minimieren-Schaltflächen ausgelöst werden?Ich finde leider nur MaximizedBoundsChanged bzw MinimumSizeChanged und das ist ja leider was anderes.
Komisch, dass es nicht unter this->MaximizeBox->Click oder so zu finden ist.In der Hilfe habe ich dann entdeckt, dass durch das Klicken dieser Schaltflächen ein Resize-Ereignis ausgelöst wird, blöderweise scheint das durch meine ResizeBegin und ResizeEnd jedoch nicht abgedeckt zu sein.
Schafft man es nämlich, genau im Moment des Bildwechsels auf Maximieren zu klicken, schmiert es mir nach wie vor mit genannter Meldung ab.Man findet zwar auch noch this->Resize, wo man einen Eventhandler einfügen könnte ... nur wie starte ich den Timer dann wieder? Bzw. ist das überhaupt das Richtige?
Hilfe, hätte ich am Anfang gewusst, dass dieses kleine Ding so in Arbeit ausartet, hätte ich es gelassen
Aber wenn, dann soll es natürlich auch bugfrei sein
-
Dann ruf im Resize Event noch folgendes auf:
System::Void Form1::Form1_Resize(System::Object^ sender, System::EventArgs^ e) { this->OnResizeBegin(e->Empty); this->OnResizeEnd(e->Empty); }
Dies löst nacheinander Form1_ResizeBegin und Form1_ResizeEnd aus, welche ja den Timer stoppen und starten.
HTH Micha
-
Das funktioniert leider nicht
Der Code lässt sich zwar kompilieren, das Problem ist aber trotzdem noch da.
Hab's auch zusätzlich mit sowas probiert, weil ich dachte, den Timer so auf jeden Fall erst einmal stoppen zu können:private: System::Void Form1_Resize(System::Object^ sender, System::EventArgs^ e) { this->tTimer->Stop(); this->OnResizeEnd(e->Empty); }
Liefert aber das gleiche Ergebnis
-
Wie hoch bzw. niedrig ist den dein Timerinterval? Ich lass zwar nur nen Counter im Label hochzählen, sehe aber deutlich das der Timer angehalten und wieder gestartet wurde.