Progressbar Value-Change-Event

  • VB.NET

Es gibt 30 Antworten in diesem Thema. Der letzte Beitrag () ist von Facebamm.

    Glaub nicht. Du könntest dir ja ein eigenes Control auf Basis der Progressbar erstellen und dort solch ein Event implementieren. Sollte nicht sonderlich schwer sein
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Aktionen sollten normalerweise nicht über solch einen Weg gehen.
    Wenn du einfach mehrere Dinge hast die getan werden sollen, dann schreib eine Methode, oder ggf. auch Property, die dann eben alle nötigen Werte mit einem aufruf anpasst...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    genauso wie du den Wert der Progressbar auch setzen musst? Verschieb das setzen der Value in diese Methode oder Property und die Anzahl der Aufrufe bleibt visuell für dich diesselbe...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    Humax schrieb:

    jedes mal machen
    musst Du nicht.
    Mach Dir eine eigene Klasse MyProgressBar Inherits ProgressBar und gib ihr das Event.
    Feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Humax schrieb:

    jedes mal machen
    musst Du nicht.Mach Dir eine eigene Klasse MyProgressBar Inherits ProgressBar und gib ihr das Event.Feddich.
    Kannst du mir dazu bissl Code geben, oder wo ich was nachlesen kann? Ich wüsste nicht, wie ich meiner Klasse ein Event zuteilen kann, dass auf einer Progressbar basiert, aber bei einer PB gar nicht exisitiert!?

    RodFromGermany schrieb:

    und wie?

    Hab die PB ganz weg gelassen und einfach für den Vorgang den Mauszeiger in "Cursors.wait" gesetzt
    @Humax So etwa:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class MyProgressBar
    2. Inherits ProgressBar
    3. Public Event ValueChanged(sender As Object, e As EventArgs) ' Event deklarieren
    4. Public Overloads Property Value As Integer
    5. Get
    6. Return MyBase.Value
    7. End Get
    8. Set(value As Integer)
    9. MyBase.Value = value
    10. RaiseEvent ValueChanged(Me, EventArgs.Empty) ' Event senden
    11. End Set
    12. End Property
    13. End Class
    Kompilieren.
    Dazu eine Form mit MyProgressBar, TrackBar und Label und dies:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    3. TrackBar1.Maximum = 100 ' TrackBar1 und MyProgressBar1 haben denselben Max-Wert
    4. End Sub
    5. Private Sub MyProgressBar1_ValueChanged(sender As Object, e As EventArgs) Handles MyProgressBar1.ValueChanged
    6. Label1.Text = MyProgressBar1.Value.ToString ' Wert anzeigen
    7. End Sub
    8. Private Sub TrackBar1_Scroll(sender As Object, e As EventArgs) Handles TrackBar1.Scroll
    9. Me.MyProgressBar1.Value = TrackBar1.Value ' Wert setzen
    10. End Sub
    11. End Class


    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    VB-Fragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „RodFromGermany“ ()

    RodFromGermany schrieb:

    Kompilieren


    Sollte das deklarieren heißen?

    Musste es etwas umschreiben, aber ja das funktioniert prima. Danke
    Habe jetzt allerdings auch hier das Problem, das wie bei einer "echten" Progressbar der Balken nicht voll gefüllt (bzw. angezeigt) wird.
    Das Maximum der MyProgressbar1 und der sichtbaren Progressbar1 wird berechnet, Value auf 0 gesetzt.
    Bei meinen Tests ist das Maximum dann 317 und beide Progressbars haben am ende auch diese Value, aber der grüne Fortschrittsbalken wird nicht mal bis zur hälfte gefüllt (angezeigt, value = wie berechnet 317), wenn ich die Progressbar wieder mit

    VB.NET-Quellcode

    1. progressbar1.visible = false
    ausblende. Anscheinend geht der Fortschritt zu schnell. Wenn ich anstelle

    VB.NET-Quellcode

    1. progressbar1.visible = false
    einen timer mit 500MS starte und dort die PB ausblende wird der Fortschritt dann ganz angezeigt.
    Gibt es da eine bessere Möglichkeit anstelle des timers oder soll ich das einfach so lassen?
    ich hab das mal geschrieben, aber nicht getestet.

    Spoiler anzeigen

    C#-Quellcode

    1. public class Processbar : Control
    2. {
    3. private event Action<Processbar, double> ValueChange;
    4. private Point _textloc;
    5. private double _deltaValue;
    6. private Rectangle _processRect;
    7. private string _text;
    8. #region Properties
    9. private double _maxValue = 100;
    10. public double MaxValue {
    11. get => _maxValue;
    12. set {
    13. if (MaxValue < Value)
    14. {
    15. _maxValue = Value;
    16. }
    17. else
    18. {
    19. _maxValue = value;
    20. }
    21. UpdateDeltaValue();
    22. Invalidate();
    23. }
    24. }
    25. private double _minValue = 0;
    26. public double MinValue {
    27. get => _minValue;
    28. set {
    29. if (MinValue > Value)
    30. {
    31. _minValue = Value;
    32. }
    33. else
    34. {
    35. _minValue = value;
    36. }
    37. UpdateDeltaValue();
    38. Invalidate();
    39. }
    40. }
    41. private double _Value;
    42. public double Value {
    43. get => _Value;
    44. set {
    45. if (Value < MinValue)
    46. throw new IndexOutOfRangeException();
    47. if (Value > MaxValue)
    48. throw new IndexOutOfRangeException();
    49. _Value = value;
    50. ValueChange?.Invoke(this, value);
    51. Invalidate();
    52. }
    53. }
    54. private Color _ProcessColor;
    55. public Color ProcessColor {
    56. get => _ProcessColor;
    57. set {
    58. _ProcessColor = value;
    59. BrushProcess = new SolidBrush(value);
    60. Invalidate();
    61. }
    62. }
    63. private bool _ValueVisible;
    64. public bool ValueVisible {
    65. get => _ValueVisible;
    66. set {
    67. _ValueVisible = value;
    68. Invalidate();
    69. }
    70. }
    71. #endregion
    72. #region Settings
    73. private SolidBrush BrushProcess;
    74. #endregion
    75. public Processbar()
    76. {
    77. ControlStyles styles = ControlStyles.ResizeRedraw
    78. | ControlStyles.SupportsTransparentBackColor
    79. | ControlStyles.UserPaint;
    80. SetStyle(styles, true);
    81. _maxValue = 100;
    82. _minValue = 0;
    83. _Value = 20;
    84. ValueVisible = false;
    85. }
    86. protected override void OnPaint(PaintEventArgs e)
    87. {
    88. Graphics graphics = e.Graphics;
    89. if (BrushProcess != null){
    90. graphics.FillRectangle(BrushProcess, _processRect);
    91. if (ValueVisible)
    92. {
    93. TextRenderer.DrawText(graphics, _text, Font, _textloc, ForeColor);
    94. }
    95. }
    96. }
    97. protected override void OnSizeChanged(EventArgs e)
    98. {
    99. UpdateRect();
    100. }
    101. private void UpdateRect()
    102. {
    103. double step = Width / _deltaValue;
    104. double width = (Value - MinValue) * step;
    105. Point topcorner = Point.Empty;
    106. Size progressSize = new Size((int) width, Height);
    107. _processRect = new Rectangle(Point.Empty, progressSize);
    108. UpdateText();
    109. }
    110. private void UpdateDeltaValue()
    111. {
    112. _deltaValue = MaxValue - MinValue;
    113. UpdateText();
    114. }
    115. private void UpdateText()
    116. {
    117. double textValue = 100 * Value / _deltaValue;
    118. _text = $"{Math.Round(textValue, 1)}%";
    119. Size sizeText = TextRenderer.MeasureText(_text, Font);
    120. int textX = (Width - sizeText.Width) / 2;
    121. int textY = (Height - sizeText.Height) / 2;
    122. _textloc = new Point(textX, textY);
    123. }
    124. }
    Also der Anwender öffnet eine Datei, die dann eingelesen und verarbeitet wird.
    Es wird dabei unter anderem ein Treeview befüllt.
    Für jeden Knoten wird im Treeview die Value-Eigenschaft der Progressbar um 1 erhöht. (Vorher wurde die max Value ermittelt und gesetzt).
    Da je nach eingelesener Datei große Unterschiede in der Anzahl der Knoten sind (es können blos zehn sein, aber auch mehrere hundert), dauert es unterschiedlich lange bis die Datei verarbeitet und der Inhalt im Treeview angezeigt wird, deshalb zur Fortschrittsanzeige die Progressbar.

    Code sieht so aus:

    VB.NET-Quellcode

    1. ProgressBar1.Value = 0
    2. ' berechnen und setzen des maximums
    3. ProgressBar1.Visible = True
    4. TreeViewfüllen()


    Dann wird das Treeview gefüllt (habe ich mal verkürzt dargestellt, der ablauf ist der selbe, nur mit mehr Knoten...)

    VB.NET-Quellcode

    1. Public Sub TreeViewfüllen()
    2. If Spielstand.basis(0) Is Nothing Then Exit Sub
    3. Dim BasisIndex As Integer = 0
    4. Dim NodeIndex As Integer = 0
    5. TreeView1.Nodes.Clear()
    6. For Each Basis In Spielstand.basis
    7. MyProgressBar1.Value += 1
    8. TreeView1.Nodes.Add(Basis.Name)
    9. My.Application.DoEvents()
    10. Next
    11. TreeView1.Focus()
    12. TreeView1.SelectedNode = TreeView1.Nodes(0)
    13. End Sub


    und anschließend die PB wieder ausgeblendet

    VB.NET-Quellcode

    1. My.Application.DoEvents()
    2. Me.Cursor = Cursors.Arrow
    3. progressbar1.visible = false


    Wenn ich das Progressbar1.visible=false in einen Timer aufrufe, nach 500ms wird der Fortschrittsbalken ganz gefüllt, ansonsten nur so bis zur Hälfte.
    Ist Für mich im Grunde mit dem Timer OK!
    Wie groß ist der wert in Spielstand.basis bzw. wie viele Elemente liegen da drinnen und was ist dein Maximum deiner progressbar1?

    Lass dir doch mal die werte ausgeben und vergleich sie mal, vllt. sind sie ja gar nicht gleich groß?
    Basis kann ein Wert von 1- 8 sein.
    Darin können dann ein paar Schiffe sein, beliebig viele Gegenstände, beliebig viele Soldaten etc.
    Ich habe hier Spielstände da wird die Progressbar.Maximum mit 317 berechnet, aber auch nur mit 10, das ist immer anders, aber ich habe geprüft, wenn ich die Progressbar ausblende, dann hat progressbar1.value den selben Wert wie progressbar1.maximum, also sollte der grüne Fortschrittsbalken ganz voll sein. - Was er ja auch ist, wenn ich dann im Timer die PB ausblende
    Also offensichtlich ist es ein programmier Fehler, die frage ist nur wo dein Fehler ist.
    Um das zu beantworten, brauche wir alles was die PB manipuliert. Auch den Designer wäre nett.

    Manchmal sieht man den eigenen Fehler nicht :D