Hallo,
ich möchte den vorhandenen Text des Buttons von "play" auf "stop" setzten, wenn dieser gedrückt wurde.
dazu habe ich folgendes eingebaut:
Windows-Form-Anwendung unter VS2017:
private void button1_Click_1(object sender, EventArgs e)
{
if (button1.Text == "play")
{
textBox1.Enabled = false;
comboBox1.Enabled = false;
button1.Text = "stop";
......noch mehr code.......
In der Initalisierung und in den Properties ist der Text des Buttons auf "play" gesetzt worden.
Nehme ich ein frisches Projekt und mache dort das gleiche, dann funktioniert das.
Auch funktionieren alle anderen beiden Anweisungen im Beispiel oben.
Nehme ich alle Funktionen - bis auf die Zeile "button1.text = "xxx";" raus, ändert sich der Text komischer weise. Auch wenn es die erste Zeile wird.
Wo kann ich nun weiter suchen, warum der Text nicht geändert wird?
--
Mit freundlichen Grüßen,
Matthias Lach
Mit Hilfe des Debuggers kannst du herausfinden, von welchen Steuerelementen aus dieser Eventhandler aufgerufen wird. Setz dir einen Breakpoint, und wenn dort angehalten wird, schau dir den Inhalt von sender
an. So kannst du nachvollziehen, was in deinem Code in welcher Reihenfolge abläuft.
Weeks of programming can save you hours of planning
Anstelle einer Textprüfung wäre es sauberer wenn sich dein Form den aktuellen Zustand merkt.
Hier wäre ein bool mit dem aktuellen Zustand für isPlaying z.B. eine bessere Form.
Wenn es mehr zustände gibt, wäre auch ein Enum hilfreich.
Texte können sich mit der Zeit auch mal ändern, bei Mehrsprachigkeit wäre es sogar fatal alle Sprachen durchprüfen zu wollen.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
hallo, und danke für die Antworten.
--
Mit freundlichen Grüßen,
Matthias Lach
Der Text im Button wird erst geändert wenn die Methode beendet wird.
Was kommt denn noch bei "......noch mehr code......." ?
Lass das mal alles weg was danach kommt.
Grüße Bernd
Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3
Weiters kann man auch hier bei Irrklang spicken, Beispielcode von Projekt Nr. 6:
...
// pauses or unpauses the currently playing sound
private void PauseButton_Click(object sender, System.EventArgs e)
{
if (currentlyPlayingSound != null)
{
currentlyPlayingSound.Paused = !currentlyPlayingSound.Paused;
UpdatePauseButtonText();
}
}
// Updates the text on the pause button
private void UpdatePauseButtonText()
{
if (currentlyPlayingSound != null)
{
if (currentlyPlayingSound.Paused)
PauseButton.Text = "Play";
else
PauseButton.Text = "Pause";
}
else
PauseButton.Text = "";
}
...
Goalkicker.com // DNC Magazine for .NET Developers // .NET Blogs zum Folgen
Software is like cathedrals: first we build them, then we pray 😉
wenn ich alles auskommentiere, und nur das "text = "xxx" nutze, dann geht da auch.
Ich gucke mir das Thema mit dem blockierten GUI mal an und versuche das umzusetzen.
--
Mit freundlichen Grüßen,
Matthias Lach
auch wenn es nicht "sauber" ist, hier mal der komplette Code vom Button1:
private void button1_Click_1(object sender, EventArgs e)
{
if (button1.Text == "play")
{
button1.Text = "stop"; // und DAS passiert nicht sofort, sondern erst wenn der Sound fertig ist!
textBox1.Enabled = false;
comboBox1.Enabled = false;
var song = textBox1.Text;
int output = comboBox1.SelectedIndex;
ISoundDeviceList sndDev = new ISoundDeviceList(SoundDeviceListType.PlaybackDevice);
ISoundEngine engine = new ISoundEngine(SoundOutputDriver.AutoDetect, SoundEngineOptionFlag.DefaultOptions, sndDev.getDeviceID(output));
try
{
engine.Play2D(song, false);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
while (engine.IsCurrentlyPlaying(song) == true)
{
Thread.Sleep(500);
}
engine.RemoveSoundSource(song);
// button1.Text = "play"; // ist zu schnell erledigt, da der Song zu erst gespielt wird - optisch sieht man das nie.
textBox1.Enabled = true;
comboBox1.Enabled = true;
}
else if (button1.Text == "stop")
{
//engine.currentlyPlayingSound.Stop();
//engine.RemoveSoundSource(song);
MessageBox.Show("Stop by stop");
button1.Text = "play";
}
Das Thema mit "sauber" programmieren werde ich dann gerne mal lernen und das kleine Projekt hier dazu nutzen um Eure Vorschläge umzusetzen.
Danke schon mal für die Unterstützung und die Geduld mit mir.
--
Mit freundlichen Grüßen,
Matthias Lach
Das Problem ist, dass dein Event erst einmal durchlaufen sein muss, damit die UI auch neu gerendert werden kann.
Da du aber auch eine while schleife hast, die dann noch per Thread.Sleep rund 0,5 Sekunden warten muss, friert auch deine UI solange ein, bis dein Sound abgespielt wurde.
Solche Dinge lässt man mit einem Hintergrund Thread machen bzw. in diesem Fall mit einem BackgroundWorker.
Dann musst du dir aber auch mal den Link anschauen, den david.m dir gepostet hat.
Da wird das Problem, dass sehr häufig vorkommt, behandelt und dir Wege aufgezeigt, wie es gelöst werden kann.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
Mach es dir doch nicht unnötig kompliziert. Wenn das Beispiel bei dir funktioniert - warum solltest du denn dann noch Thread.Sleep einbauen?
Das Fenster wird, wie T-Virus schon gesagt hat, erst neu gezeichnet, wenn alle Events abgearbeitet sind. Und das ist bei dir eben erst frühestens nach 500ms der Fall. Wenn du wissen willst, warum das so ist, und wie das alles "unter der Haube" funktioniert, schau dir mal ein Buch zum Thema WinForms an~~:::
* Hab ich das entsprechende Kapitel übersehen, oder gibt es in dem Buch nur eine Einführung in WPF?
Weeks of programming can save you hours of planning
@MrSparkle
In den neueren Büchern wird nur noch WPF behandelt.
Im 2008 gab es noch Windows Forms Kapitel.
Link:
http://openbook.rheinwerk-verlag.de/visual_csharp/visual_csharp_13_001.htm
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
In dem Vorgängerbuch Visual C# 2008 gibt es noch ein Kapitel zu WinForms: 13 Grundlagen zum Erstellen einer Windows-Anwendung
Hab nun versucht alles Funktionen zu "bauen".
eine zum sound abspielen, 2 zum buttontext anpassen.
Nun habe ich das Problem, das ich die Variablen nicht in die Funktion bekomme, bzw wenn ich im neuen Thread auf die Werte der Combobox zugreife eine Exeption bekomme.
(Komischerweise mit deutschem Fehlertext, obwohl VS auf englisch steht.)
$exception {"Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement comboBox1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde."} System.InvalidOperationException.
Ich versuche gerade ein Thema zu finden, das die Übergabe von Werten an den Thread beahndelt.
Das muss, soweit ich herausgefunen habe, beim "new Thread" mit übergeben werden.
Doof, das ich die Engine im neuen Thread erzeuge, und in anderen Funktionen drauf zugreife mag.....
(suche noch)...
der Code sieht nun so aus:
void soundausgeben ()
{
var song = textBox1.Text;
int output = comboBox1.SelectedIndex;
ISoundDeviceList sndDev = new ISoundDeviceList(SoundDeviceListType.PlaybackDevice);
ISoundEngine engine = new ISoundEngine(SoundOutputDriver.AutoDetect, SoundEngineOptionFlag.DefaultOptions, sndDev.getDeviceID(output));
try
{
engine.Play2D(song, false);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
engine.RemoveSoundSource(song);
this.Invoke((Action)buttonplaysetzten);
}
void buttonplaysetzten()
{
button1.Text = "play";
textBox1.Enabled = true;
comboBox1.Enabled = true;
engine.currentlyPlayingSound.Stop();
engine.RemoveSoundSource(song);
MessageBox.Show("Stop by buttonplaysetzten"); //zum testen
}
void buttonstopsetzen ()
{
button1.Text = "stop";
textBox1.Enabled = false;
comboBox1.Enabled = false;
}
private void button1_Click_1(object sender, EventArgs e)
{
if (button1.Text == "play")
{
buttonstopsetzen ();
new Thread(soundausgeben).Start () ;
}
else if (button1.Text == "stop")
{
buttonplaysetzten();
}
}
}
--
Mit freundlichen Grüßen,
Matthias Lach
(Komischerweise mit deutschem Fehlertext, obwohl VS auf englisch steht.)
Die Sprache der Fehlermeldungen hat mit der Sprache des VS nichts zu tun.
Es gibt für das .NET Framework Language Packs, es reicht wenn du das entsprechende Language Pack für deutsch deinstallierst.
Habe mal versucht mir was anzulesen.
https://docs.microsoft.com/de-de/dotnet/csharp/programming-guide
oder auch
http://openbook.rheinwerk-verlag.de/visual_csharp/visual_csharp_09_001.htm
Wie bekomme ich von der erzeugten "Engine" einen Aufruf hin und kann als Parameter das Output-Device und den Titel übergeben?
Wenn ich "engine" in anderen Methode aufrufe, wissen die nicht was damit gemeint ist und sagen mit dann: > Fehlermeldung:
The name 'engine' does not exist in the current context
Und wenn ich das alles wie zuvor in einem "Rutsch" mache, dann hab ich das "GUI blockerit"-Thema.
--
Mit freundlichen Grüßen,
Matthias Lach
Stichwort Scope: Scopes in C#
void buttonplaysetzten()
{
button1.Text = "play";
textBox1.Enabled = true;
comboBox1.Enabled = true;
engine.currentlyPlayingSound.Stop();
engine.RemoveSoundSource(song);
MessageBox.Show("Stop by buttonplaysetzten"); //zum testen
}
das Objekt "engine" gibt es in der Methode buttonplaysetzen nicht.
Entweder du gibst es als Parameter mit in die Methoden, oder Intitialisierst es als Klassenvariable, was aber eigentlich auch bad practise ist.
Bsp:
void MethodeXYZ()
{
ISoundEngine engine = new ISoundEngine(SoundOutputDriver.AutoDetect, SoundEngineOptionFlag.DefaultOptions, sndDev.getDeviceID(output));
buttonplaysetzten(engine);
}
void buttonplaysetzten(ISoundEngine engine)
{
button1.Text = "play";
textBox1.Enabled = true;
comboBox1.Enabled = true;
engine.currentlyPlayingSound.Stop();
engine.RemoveSoundSource(song);
MessageBox.Show("Stop by buttonplaysetzten"); //zum testen
}
Und wenn ich das alles wie zuvor in einem "Rutsch" mache, dann hab ich das "GUI blockerit"-Thema.
Das wirst du auch weiterhin haben, solange du nicht [FAQ] Warum blockiert mein UI beachtest....
Selbst wenn ich keinen neuen Thread erzeuge bekomme, in meinem Projekt, bekomme ich das so nicht hin, da mir wohl Grundlagen fehlen und ich die Konsole-Beispeiel, die immer angegeben werden nicht verstehe. Bzw. nicht so umsetzten kann, wie ich es gerne hätte.
Als Lerntyp bin ich eher so der Visuelle-Typ.... Mir helfen konkrete Beispiele mit Erklärungen dazu.
Und du merkst das deine Herangehensweise hier vollkommen falsch ist.
Lern doch erstmal die Grundlagen.
Meinst du das Du das, was ein Professioneller Programmierer in 1-2 Jahren von Grund auf lernt in ein paar Stunden ansehen kannst?