none
dibujar barra vertical

    Pregunta

  • Hola a tod@s,

    tengo que dibujar un rectángulo solido dentro de un picturebox y he visto que tiene el inicio de coordenadas arriba a la izquierda.

    la pregunta es : como puedo poner el inicio abajo izquierda i poder dibujar la barra vertical y al incrementar una variable se incremente su altitud, (tipo vumeter)

    se que se hace con transform.... pero no me aclaro

    podeis indicarme el código correcto?

    es en vb net

    gracias de antemano

    joan


    joanVB

    lunes, 24 de abril de 2017 17:05

Respuestas

  • El timer fue agregado como parte del ejemplo. Deberías quitarlo.

    Deberías hacer el Invalidate de los pictures luego de adquirir el valor en el DataReceived.

    No uses DIBUJO dentro del Paint() de los pictureboxes. Usa los recursos que te provee el método: e.Graphics.

    Por último. Mi ejemplo te muestra en cada picturebox, el dibujo del rectángulo mediante Transform (el primero), o mediante cálculo directo. Elige el que más te guste. No tienes que usar las dos técnicas. O sí, lo que digo es que no es necesario.

    • Marcado como respuesta JoanVB martes, 25 de abril de 2017 16:29
    martes, 25 de abril de 2017 15:27
  • SolidBrush, en System.Drawing
    • Marcado como respuesta JoanVB martes, 25 de abril de 2017 16:35
    martes, 25 de abril de 2017 16:30

Todas las respuestas

  • Puedes hacerlo con Transform, yo no lo haría así, pero es muy sencillo describir la matriz

    Ejemplo, dos pictureboxes, uno aplicando una transformación y el otro haciendo el cálculo en el propio Paint

    Imports System.Drawing.Drawing2D
    
    Public Class Form1
        Dim valor As Integer = 125
    
        Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
            Dim pb As PictureBox = DirectCast(sender, PictureBox)
    
            e.Graphics.Transform = New Matrix(1, 0, 0, -1, 0, pb.Height)
            e.Graphics.FillRectangle(Brushes.Green, 0, 0, pb.Width, valor)
        End Sub
    
        Private Sub PictureBox2_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox2.Paint
            Dim pb As PictureBox = DirectCast(sender, PictureBox)
    
            e.Graphics.FillRectangle(Brushes.Yellow, 0, pb.Height - valor, pb.Width, pb.Height)
        End Sub
    End Class


    lunes, 24 de abril de 2017 19:35
  • Hola Miqui

    gracias por tu ejemplo

    parace que funciona

    el primer sub si funciona

    el segundo no (da error de compilación)

    pero almenos me funciona 1

    por cierto como puedo limitar el valor superior de la barra a p.ej. 1000

    gracias

    joan


    joanVB

    martes, 25 de abril de 2017 9:15
  • Imports System.Drawing.Drawing2D
    
    Public Class Form1
        Dim maximo As Integer = 1000
        Dim interior As LinearGradientBrush
    
        Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
            Dim pb As PictureBox = DirectCast(sender, PictureBox)
            Dim valor = Rnd() * maximo
    
            e.Graphics.Transform = New Matrix(1, 0, 0, -pb.Height / maximo, 0, pb.Height)
            e.Graphics.FillRectangle(interior, 0, 0, pb.Width, valor)
        End Sub
    
        Private Sub PictureBox2_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox2.Paint
            Dim pb As PictureBox = DirectCast(sender, PictureBox)
            Dim valor = Rnd() * maximo
    
            e.Graphics.FillRectangle(Brushes.Yellow, 0, pb.Height - pb.Height * valor / maximo, pb.Width, pb.Height)
        End Sub
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Timer1.Interval = 200
            Timer1.Enabled = True
    
            PictureBox1.Anchor = AnchorStyles.Bottom Or AnchorStyles.Left Or AnchorStyles.Top
            PictureBox2.Anchor = PictureBox1.Anchor
    
            interior = New LinearGradientBrush(New Rectangle(0, 0, 10, maximo), Color.White, Color.Green, LinearGradientMode.Vertical)
    
            Randomize()
        End Sub
    
        Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
            PictureBox1.Invalidate()
            PictureBox2.Invalidate()
        End Sub
    End Class

    Ahí tienes como establecer el valor máximo. No sé como es el input de tu programa. Aquí yo agregué un timer y el valor es calculado aleatoriamente entre 0 y maximo.

    El Paint() del picturebox1 usa la propiedad Transform del Graphics.

    En el Paint() del segundo, los límites del rectángulo a pintar se calculan allí mismo.



    martes, 25 de abril de 2017 13:43
  • hola de nuevo miqui

    ahora no me compila...

    te esplico

    el valor lo cojo de variable LECTURA (viene via serie)

    el formulario tiene 3 picturebox (1,3) el 2 es otro que no importa

    te paso codigo por si ves algo raro

    con que me funcione con una manera de barra ya me vale (la segunda manera nunca me funciono)

    espero que no te moleste

    att

    joan

    código

    --------------------------

    Imports System.Drawing.Imaging
    Imports System.Drawing.Drawing2D
    Public Class SERIE
        Dim MIX As Integer
        Dim LECTURA As Integer
        Dim DIBUJO As Graphics
        Dim DIBUJO2 As Graphics
        Dim CCOLOR As Color
        Dim LAPIZ As Pen
        Dim PINCEL As Brush
        Dim BM As Bitmap
        Dim BM2 As Bitmap
        Dim ANGULO As Single
        Dim CARGB As Color
        Dim TRAZO As Pen
        Dim sib, valor As Integer
        Dim ESCALA As Single
        Dim ample As Integer
        Dim maximo As Integer = 1000
        Dim interior As LinearGradientBrush

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            GetSerialPortNames()
            Label2.Text = 0
            BM = New Bitmap(PictureBox1.Width, PictureBox1.Height)
            DIBUJO = Graphics.FromImage(BM)
            TRAZO = New Pen(Brushes.Lime, 10)
            CheckForIllegalCrossThreadCalls = False ' DESACTIVA ERROR POR SUBPROCESO
            PictureBox1.BackColor = Color.White
            DIBUJO.Clear(Color.White)
            Timer1.Enabled = True
            Timer2.Interval = 200
            Timer2.Enabled = True
            PictureBox1.Anchor = AnchorStyles.Bottom Or AnchorStyles.Left Or AnchorStyles.Top
            PictureBox3.Anchor = PictureBox1.Anchor
            interior = New LinearGradientBrush(New Rectangle(0, 0, 10, maximo), Color.White, Color.Green, LinearGradientMode.Vertical)
        End Sub
        Sub Setup_Puerto_Serie()
            Try
                With SerialPort1
                    If .IsOpen Then
                        .Close()
                    End If
                    .PortName = ComboPorts.Text
                    .BaudRate = 115200
                    .DataBits = 8                       '// 8 data bits                                                  
                    .StopBits = IO.Ports.StopBits.One   '// 1 Stop bit
                    .Parity = IO.Ports.Parity.None      '
                    .DtrEnable = False
                    .Handshake = IO.Ports.Handshake.None
                    .ReadBufferSize = 16
                    .WriteBufferSize = 16
                    .ReceivedBytesThreshold = 1
                    .WriteTimeout = 500
                    '.Encoding = System.Text.Encoding.Default
                    .Open()                              '  ABRE EL PUERTO SERIE
                End With
            Catch ex As Exception
                MsgBox("Error a l'obrir el port serie" & ex.Message, MsgBoxStyle.Critical)
            End Try
        End Sub
        Sub GetSerialPortNames()
            ' muestra COM ports disponibles.
            Dim l As Integer
            Dim ncom As String
            Try
                ComboPorts.Items.Clear()
                For Each sp As String In My.Computer.Ports.SerialPortNames
                    l = sp.Length
                    If ((sp(l - 1) >= "0") And (sp(l - 1) <= "9")) Then
                        ComboPorts.Items.Add(sp)
                    Else
                        'hay una letra al final del COM
                        ncom = sp.Substring(0, l - 1)
                        ComboPorts.Items.Add(ncom)
                    End If
                Next
                If ComboPorts.Items.Count >= 1 Then
                    ComboPorts.Text = ComboPorts.Items(0)
                Else
                    ComboPorts.Text = ""
                End If
            Catch ex As Exception
            End Try
            ComboPorts.Text = "COM3"
        End Sub
        Private Sub BtnConectar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnConectar.Click
            Try
                If BtnConectar.Text = "Connectar" Then
                    BtnConectar.Text = "Desconnectar"
                    Setup_Puerto_Serie()
                    BtnConectar.BackColor = System.Drawing.Color.Lime
                    DIBUJO.Clear(Color.White)
                    PictureBox1.Invalidate()
                Else
                    If SerialPort1.IsOpen Then
                        SerialPort1.Close()
                        DIBUJO.Clear(Color.White)
                    End If
                    BtnConectar.Text = "Connectar"
                    BtnConectar.BackColor = System.Drawing.Color.Yellow
                    DIBUJO.Clear(Color.White)
                    PictureBox1.Invalidate()
                End If
            Catch ex As Exception
            End Try
        End Sub
        Private Sub BtnBuscarComm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnBuscarComm.Click
            GetSerialPortNames()
        End Sub
        Private Sub Button_enviar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_enviar.Click
            sib = 0
            Try
                SerialPort1.Write(Me.Text_denviados.Text)
                Me.Text_drecibidos.Clear()
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        End Sub

        Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
            Try
                PictureBox2.BackColor = Color.Red
                Dim valor As String = SerialPort1.ReadLine
                LECTURA = valor
                ESCALA = 1
                If LECTURA > 1000 Then
                    LECTURA = 1000
                    ample = 100
                End If
                Text_drecibidos.Text = LECTURA
                Label2.Text = LECTURA
                TextBox1.Text = ample
                sib = sib + 1
                CCOLOR = Color.LimeGreen
                If LECTURA < 100 Then
                    CCOLOR = Color.Red
                End If
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
            '   barres()
            TextBox2.Text = SerialPort1.ReadBufferSize
            PictureBox2.BackColor = Color.Green
        End Sub
        Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
            Dim pb As PictureBox = DirectCast(sender, PictureBox)
            '  Dim valor = LECTURA
            DIBUJO.Transform = New Matrix(1, 0, 0, -pb.Height / maximo, 0, pb.Height)
            DIBUJO.FillRectangle(interior, 0, 0, pb.Width, LECTURA)
        End Sub
        Private Sub PictureBox3_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox3.Paint
            Dim pb As PictureBox = DirectCast(sender, PictureBox)
            '  Dim valor = Rnd() * maximo
            DIBUJO2.FillRectangle(Brushes.Yellow, 0, pb.Height - pb.Height * LECTURA / maximo, pb.Width, pb.Height)
        End Sub

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Me.Text_denviados.Clear()
        End Sub
        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Me.Close()
            End
        End Sub
        Private Sub Button3_Click(sender As Object, e As EventArgs)
            CCOLOR = Color.Black
            PINCEL = New SolidBrush(CCOLOR)
            'LAPIZ = New Pen(CCOLOR)
            DIBUJO.FillRectangle(PINCEL, 10, 10, 1000, 100)
            PictureBox1.Image = BM
        End Sub
        Private Sub SortirToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SortirToolStripMenuItem.Click
            Me.Close()
            End
        End Sub
        Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
            Label3.Text = Date.Now.ToLongTimeString
        End Sub
        Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
            PictureBox1.Invalidate()
            PictureBox3.Invalidate()
        End Sub

        Private Sub B_esborrar_Click(sender As Object, e As EventArgs) Handles B_esborrar.Click
            DIBUJO.Clear(Color.White)
            PictureBox1.Image = BM
        End Sub
    End Class


    joanVB

    martes, 25 de abril de 2017 14:44
  • El timer fue agregado como parte del ejemplo. Deberías quitarlo.

    Deberías hacer el Invalidate de los pictures luego de adquirir el valor en el DataReceived.

    No uses DIBUJO dentro del Paint() de los pictureboxes. Usa los recursos que te provee el método: e.Graphics.

    Por último. Mi ejemplo te muestra en cada picturebox, el dibujo del rectángulo mediante Transform (el primero), o mediante cálculo directo. Elige el que más te guste. No tienes que usar las dos técnicas. O sí, lo que digo es que no es necesario.

    • Marcado como respuesta JoanVB martes, 25 de abril de 2017 16:29
    martes, 25 de abril de 2017 15:27
  • funciona !!!!

    eres un artista miqui

    y muy bueno lo del gradiente de la barra :-)

    si quiero la barra solida como lo hago?

    de nuevo eres un artista

    saludos 

    joan

    pd . te debo 1


    joanVB

    martes, 25 de abril de 2017 16:28
  • SolidBrush, en System.Drawing
    • Marcado como respuesta JoanVB martes, 25 de abril de 2017 16:35
    martes, 25 de abril de 2017 16:30
  • por cierto 

    los números del ranking que significan?

    y las medallas?

    hay premios? jajja


    joanVB

    martes, 25 de abril de 2017 16:35
  • En realidad no significan nada. Los números.

    Existe un reconocimiento de parte de Microsoft y su programa de MVP. Existe desde los tiempos de cuando la ayuda entre usuarios se hacía a través de compuserve. Premia a los que de manera regular dedican su tiempo a colaborar en los foros.

    martes, 25 de abril de 2017 17:12