herby-z
Goto Top

Visual Studio 2010 einfache analoge Uhr erstellen

Hallo,

ich versuche gerade mit VB2010 eine analoge Uhr zu erstellen.

Anforderungen:

- die Uhrzeiger (lineShape) sollten manuell einstellbar sein. (evtl. über NumericUpDown)
- die eingestellte Uhrzeit sollte in einem Textfeld angezeigt werden.

Mein Hauptproblem besteht darin die richtigen Koordinaten für die Zeiger einzustellen.

Für Euere Unterstützung vorab schon besten Dank.

Gruß
Herby_z

Content-ID: 266684

Url: https://administrator.de/contentid/266684

Ausgedruckt am: 22.11.2024 um 17:11 Uhr

eisbein
Lösung eisbein 18.03.2015 aktualisiert um 14:03:58 Uhr
Goto Top
Hallo!

Ich habe eine ähnliche Anwendung so gelöst:

Anfangspunkt des Zeigers ist der Mittelpunkt, da ist schon mal einfach

Den Endpunkt des Zeigers habe ich folgendermaßen berechnet und den Winkel mittels Timer im Sekunden/Minuten/Stundentakt aktualisiert.

Gruß
Eisbein
Herby-z
Herby-z 18.03.2015 um 14:08:06 Uhr
Goto Top
Bewegen tut sich was, aber nicht wie gewünscht face-sad

Mein Code für den Minutenzeiger per NumericUpDown:

Private Sub numMin_ValueChanged(sender As System.Object, e As System.EventArgs) Handles numMin.ValueChanged
radWinkel = numMin.Value / 180 * Math.PI
x_koordinate = Math.Cos(radWinkel) * 125
y_koordinate = Math.Sin(radWinkel) * 125
lineMin.X2 += x_koordinate
lineMin.Y2 += y_koordinate
End Sub

Das LineShape lineMin hat folgende Eigenschaften:
X1=145
X2=145
Y1=145
Y2=20
BorderWith=6

Steht also auf 12Uhr
emeriks
Lösung emeriks 18.03.2015 aktualisiert um 15:04:42 Uhr
Goto Top
Hi,

hier ein Bsp:

Form1.Designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Das Formular überschreibt den Löschvorgang, um die Komponentenliste zu bereinigen.  
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Wird vom Windows Form-Designer benötigt.  
    Private components As System.ComponentModel.IContainer

    'Hinweis: Die folgende Prozedur ist für den Windows Form-Designer erforderlich.  
    'Das Bearbeiten ist mit dem Windows Form-Designer möglich.    
    'Das Bearbeiten mit dem Code-Editor ist nicht möglich.  
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
    Me.ShapeContainer1 = New Microsoft.VisualBasic.PowerPacks.ShapeContainer()
    Me.MinutesShape = New Microsoft.VisualBasic.PowerPacks.LineShape()
    Me.SecondsShape = New Microsoft.VisualBasic.PowerPacks.LineShape()
    Me.HoursShape = New Microsoft.VisualBasic.PowerPacks.LineShape()
    Me.Label1 = New System.Windows.Forms.Label()
    Me.SuspendLayout()
    '  
    'ShapeContainer1  
    '  
    Me.ShapeContainer1.Location = New System.Drawing.Point(0, 0)
    Me.ShapeContainer1.Margin = New System.Windows.Forms.Padding(0)
    Me.ShapeContainer1.Name = "ShapeContainer1"  
    Me.ShapeContainer1.Shapes.AddRange(New Microsoft.VisualBasic.PowerPacks.Shape() {Me.HoursShape, Me.MinutesShape, Me.SecondsShape})
    Me.ShapeContainer1.Size = New System.Drawing.Size(292, 273)
    Me.ShapeContainer1.TabIndex = 0
    Me.ShapeContainer1.TabStop = False
    '  
    'MinutesShape  
    '  
    Me.MinutesShape.Name = "MinutesShape"  
    Me.MinutesShape.X1 = 117
    Me.MinutesShape.X2 = 192
    Me.MinutesShape.Y1 = 98
    Me.MinutesShape.Y2 = 121
    '  
    'SecondsShape  
    '  
    Me.SecondsShape.Name = "SecondsShape"  
    Me.SecondsShape.X1 = 94
    Me.SecondsShape.X2 = 169
    Me.SecondsShape.Y1 = 58
    Me.SecondsShape.Y2 = 81
    '  
    'HoursShape  
    '  
    Me.HoursShape.Name = "HoursShape"  
    Me.HoursShape.X1 = 121
    Me.HoursShape.X2 = 196
    Me.HoursShape.Y1 = 126
    Me.HoursShape.Y2 = 149
    '  
    'Label1  
    '  
    Me.Label1.AutoSize = True
    Me.Label1.Location = New System.Drawing.Point(13, 13)
    Me.Label1.Name = "Label1"  
    Me.Label1.Size = New System.Drawing.Size(39, 13)
    Me.Label1.TabIndex = 1
    Me.Label1.Text = "Label1"  
    '  
    'Form1  
    '  
    Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
    Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
    Me.ClientSize = New System.Drawing.Size(292, 273)
    Me.Controls.Add(Me.Label1)
    Me.Controls.Add(Me.ShapeContainer1)
    Me.Name = "Form1"  
    Me.Text = "Form1"  
    Me.ResumeLayout(False)
    Me.PerformLayout()

  End Sub
  Friend WithEvents ShapeContainer1 As Microsoft.VisualBasic.PowerPacks.ShapeContainer
  Friend WithEvents SecondsShape As Microsoft.VisualBasic.PowerPacks.LineShape
  Friend WithEvents MinutesShape As Microsoft.VisualBasic.PowerPacks.LineShape
  Friend WithEvents HoursShape As Microsoft.VisualBasic.PowerPacks.LineShape
  Friend WithEvents Label1 As System.Windows.Forms.Label

End Class

Form1.vb
Imports System.Drawing.Drawing2D
Imports Microsoft.VisualBasic.PowerPacks

Public Class Form1
  Dim WithEvents mTimer As New Timers.Timer(10)

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    With SecondsShape
      .X1 = ShapeContainer1.Width / 2
      .Y1 = ShapeContainer1.Height / 2
      .X2 = .X1
      .Y2 = .Y2 - 50
    End With
    With MinutesShape
      .X1 = ShapeContainer1.Width / 2
      .Y1 = ShapeContainer1.Height / 2
      .X2 = .X1
      .Y2 = .Y2 - 50
    End With
    With HoursShape
      .X1 = ShapeContainer1.Width / 2
      .Y1 = ShapeContainer1.Height / 2
      .X2 = .X1
      .Y2 = .Y2 - 25
    End With

    mTimer.Start()
  End Sub

  Private Sub mTimer_Elapsed(sender As Object, e As Timers.ElapsedEventArgs) Handles mTimer.Elapsed
    If Me.InvokeRequired Then
      Me.Invoke(New Action(Of Object, Timers.ElapsedEventArgs)(AddressOf mTimer_Elapsed), sender, e)
    Else
      Static µSecond As Integer = 0
      Static µMinute As Integer = 0
      Static µHour As Integer = 0
      Static µMinuteTick As Double = 0
      Static µHourTick As Double = 0
      µSecond += 1

      If µSecond = 60 Then
        µSecond = 0
      End If

      µMinuteTick += (1 / 60)
      If µMinuteTick >= 60 Then
        µMinuteTick = 0
      End If

      µHourTick += (1 / 720)
      If µHourTick >= 12 Then
        µHourTick = 0
      End If

      µMinute = Fix(µMinuteTick)
      µHour = Fix(µHourTick)


      Label1.Text = µHour.ToString("00") & ":" & µMinute.ToString("00") & ":" & µSecond.ToString("00")  


      With SecondsShape
        Dim µR = (6 * (µSecond - 15)) / 180 * Math.PI
        .X2 = .X1 + Math.Cos(µR) * 50
        .Y2 = .Y1 + Math.Sin(µR) * 50
      End With
      With MinutesShape
        Dim µR = (6 * (µMinuteTick - 15)) / 180 * Math.PI
        .X2 = .X1 + Math.Cos(µR) * 50
        .Y2 = .Y1 + Math.Sin(µR) * 50
      End With
      With HoursShape
        Dim µR = (6 * (µHourTick - 15)) / 180 * Math.PI
        .X2 = .X1 + Math.Cos(µR) * 25
        .Y2 = .Y1 + Math.Sin(µR) * 25
      End With
    End If
  End Sub
End Class
Herby-z
Herby-z 18.03.2015 um 15:01:59 Uhr
Goto Top
Danke aber viel zu komplex für mich.

Möchte einfach eine Linie über einen Button oder NumericUpDown um seine Achse drehen !

Danke
Herby_z
emeriks
emeriks 18.03.2015 um 15:06:42 Uhr
Goto Top
Auf einmal einfach bloß ne Linie? Oben heißt es noch analoge Uhr ....
Na dann pack die Timer Routine ins Button.Click und fertig.

E.
Herby-z
Herby-z 18.03.2015 um 16:21:01 Uhr
Goto Top
Ja, eine einfache analoge Uhr !

Anforderungen:

- die Uhrzeiger (lineShape) sollten manuell einstellbar sein. (evtl. über NumericUpDown)
- die eingestellte Uhrzeit sollte in einem Textfeld angezeigt werden.

Es reicht mir ein Zeiger, den zweiten schaffe so gar ich !

Dein Code ist mir zuviel, will ja auch gar nicht das die Uhr von alleine läuft !

Zur Erklärung: Möchte für meinen Sohn ein Uhrlehrnprogramm erstellen.
Ich stelle die analoge Uhrzeit manuell ein und er tippt in ein Textfeld die digitale Zeit.

Leider scheitert es bei der Analogen Uhr.

Wenn ich eine Linie um 360 Grad drehen kann schaffe ich den Rest vermutlich allein.

P.S. Das Programm läuft eigentlich schon, nur variiert die Zeigerlänge beim verstellen, da ich die Punkte abschätze.
emeriks
emeriks 18.03.2015 um 17:27:01 Uhr
Goto Top
Was sollen die vielen "!" jetzt ausdrücken? Ich will bloß helfen, ok?

Eine Linie, die sich um 360° dreht stellt aber eine seeeehr beschränkte Uhr dar. Sie könnte ausschließlich Zeiten wie 06:00 Uhr anzeigen. (Und noch 11 weitere Kombinationen, die man aber erstmal berechnen müsste).

Du musst die Linie also eben nicht um 360° drehen sondern um einen ihrer Endpunkte.

Wie auch immer. Ich dachte, Du könntest VB lesen? Du brauchst doch nur den Ansatz aus der Sub mTimer_Elapsed nehmen und mit Übergabewerten kombinieren. z.B. so

 Private Sub SetTime(µHour As Integer,  µMinute As Integer)
    If Me.InvokeRequired Then
      Me.Invoke(New Action(Of Integer, Integer)(AddressOf SetTime), µHour, µMinute)
    Else
      Static µSecond As Integer = 0

      With SecondsShape
        Dim µR = (6 * (µSecond - 15)) / 180 * Math.PI
        .X2 = .X1 + Math.Cos(µR) * 50
        .Y2 = .Y1 + Math.Sin(µR) * 50
      End With
      With MinutesShape
        Dim µR = (6 * (µMinute - 15)) / 180 * Math.PI
        .X2 = .X1 + Math.Cos(µR) * 50
        .Y2 = .Y1 + Math.Sin(µR) * 50
      End With
      With HoursShape
        Dim µR = (6 * ((µHour * 5) - 15)) / 180 * Math.PI
        .X2 = .X1 + Math.Cos(µR) * 25
        .Y2 = .Y1 + Math.Sin(µR) * 25
      End With
    End If
  End Sub

So. das kombinierst Du jetzt noch mit zwei NumericUpDowns und gut is.

 Private Sub nupHour_ValueChanged(sender As Object, e As EventArgs) Handles nupHour.ValueChanged, nupMinute.ValueChanged
    SetTime(nupHour.Value, nupMinute.Value)
  End Sub

E.
Herby-z
Herby-z 19.03.2015 um 08:22:14 Uhr
Goto Top
Danke für die Unterstützung.

Hier nochmal was ich gebraucht habe:

Private Sub numStd_ValueChanged(sender As System.Object, e As System.EventArgs) Handles numStd.ValueChanged
Dim i = (6 * ((numStd.Value) - 15)) / 180 * Math.PI
lineStd.X2 = lineStd.X1 + Math.Cos(i) * 75
lineStd.Y2 = lineStd.Y1 + Math.Sin(i) * 75
End Sub