Calcular porcentaje

Iniciado por Meta, 21 Agosto 2017, 12:50 PM

0 Miembros y 1 Visitante están viendo este tema.

Meta

Hola:

Hice esta aplicación para enviar datos a EEPROM tipo 24LCxx por I2C con Arduino. Tabajando con C#, ya puedo enviar los datos al puerto serie. Puede contar los bytes enviados. El problema, que estoy machacando la cabeza que no hay manera de hacer fucnionar en la barra del progreso que me cuenta el "label_Por_ciento" del 0 % al 100 %.



Ya puedeo envair datos y cancelarlo.
Código (csharp) [Seleccionar]
        private void TestDoEvents()
        {
            byte[] archivo = File.ReadAllBytes(textBox_ubicacion_archivo.Text); // Carga el archivo en el array.

            progressBar_barrra_progreso.Maximum = archivo.Length; // Hasta donde llegue el tamaño del archivo.

            for (int i = 0; i <= archivo.GetUpperBound(0); i++)
            {
                serialPort1.Write(archivo, i, 1);

                progressBar_barrra_progreso.Value = i;

                label_Bytes_transmitidos.Text = i.ToString() + " Bytes.";

                Application.DoEvents();
                if (alto == true)
                {
                    alto = false;
                    break; // TODO: might not be correct. Was : Exit For
                }
            }
            button_Cancelar.Text = "Arranque";
        }


Botón.
Código (csharp) [Seleccionar]
        private void button_Cancelar_Click(object sender, EventArgs e)
        {
            if (button_Cancelar.Text == "Arranque")
            {
                button_Cancelar.Text = "Cancelar";
                TestDoEvents();
                progressBar_barrra_progreso.Value = 0; // Resetear progressBar a 0.
                label_Bytes_transmitidos.Text = "0";
            }
            else
            {
                if (alto == true)
                {
                    alto = false;
                }
                else
                {
                    alto = true;
                    button_Cancelar.Text = "Arranque";
                }
            }
        }


¿Alguna idea?

Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

ivancea96

Qué es el "label_Por_ciento"? Dónde lo modificas?

Serapis

#2
La barra de progreso, siempre va desde el valor mínimo al valor máximo.

Para que vaya del 0 al 100, esos deben ser los valores límites.

Si necesitas que se ajuste a esos límites, una de dos, o pones esos límites y trabajas con los que hay o pones los que hay y formateas esos límites (sin embargo, no tenemos control sobre la presentación, el redibujado del valor, así que exigiría crear tu propio control. y prograsmar un evento 'Changed' (o ValueChanged), que es donde redibujamos el valor y con la ayuda de una propiedad "AjustarSiemprealTantoPorCiento" = TRUE
Como dudo que vayas a crear un control de usuario solo para eso, me remito a la solución sobre el progressbar...

- Puesto el control del 0 al 100: Supongamos que vas a leer 63147 bytes... desde un bucle,
   Float PorCiento1

   // pgbProgreso, aquíes un control ProgressBar
   pgbProgreso.Min = 0
   pgbProgreso.Max = 100 // en realidad solo llegaremos al 99, pero dejamos 1 más por si los decimales alcanzan el 100, para que no 'cante' error...

   PorCiento1 = (63147 / 100)
   Bucle para k desde 0 a 63146
      // cosas por hacer
      pgbProgreso.Value = (porciento1 * k)
      // otras cosas por hacer
   Fin Bucle


p.d.: No había visto la imagen (hasta enviar la respuesta) y que no usas un control progressbar, si no que muestras el resultado en un simple label... modifico el pseudocódigo previo:

   Float PorCiento1

   //lblProgreso, sería aquí un label
   PorCiento1 = (63147 / 100)
   Bucle para k desde 0 a 63146
      // cosas por hacer
      // Damos formato al valor para que tenga al menos 2 decimales.
       // OJO:
       //     La barra "\" es una división entera.
       //     INT es una función de conversión donde se elimina los decimales.
       //     ToString, no deja lugar a dudas....
      lblProgreso.Text = (Int((porciento1 * k) * 100) \ 100).ToString & "%"
      // otras cosas por hacer
   Fin Bucle

Meta

Buenas:

Pensaba que era algo así.
Código (csharp) [Seleccionar]
label_Por_ciento.Text = ((progressBar_barrra_progreso.Value / archivo.Count()) * 100).ToString() + "%";

Voy a probar lo que dices.

Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Meta

Averiguado, gracias por la ayuda.

Código (csharp) [Seleccionar]
      // Variables.
        bool alto = false;
        int N = 0;
        int P = 0;
        int resul = 0;

        private void TestDoEvents()
        {
            // Carga el archivo en el array.
            byte[] archivo = File.ReadAllBytes(textBox_ubicacion_archivo.Text);

            // Hasta donde llegue el tamaño del archivo.
            progressBar_barrra_progreso.Maximum = archivo.Length;

            // Guarda la cantidad de Bytes del archivo en la variable.
            N = archivo.Length - 1;

            // Transmite byte en byte los datos del archivo al puerto serie.
            for (int i = 0; i <= archivo.GetUpperBound(0); i++)
            {
                // Enviando archivo al puerto serie.
                serialPort1.Write(archivo, i, 1);
               
                // Números de Bytes.
                P = i;
               
                // Resultado de la regla de tres. Cálculo del porcentaje de la barra de progreso.
                resul = 100 * i / N;
               
                // Muestra barra del progreso.
                progressBar_barrra_progreso.Value = i;

                // Muestra la cantidad de Bytes enviados.
                label_Bytes_transmitidos.Text = i.ToString() + " Bytes.";

                // Muestra la cantidad en porciento archivo enviado.
                label_Por_ciento.Text = resul + " %";

                // Evento de cancelación.
                Application.DoEvents();
                if (alto == true)
                {
                    alto = false;
                    break; // TODO: might not be correct. Was : Exit For
                }
            }
            button_Cancelar.Text = "Arranque";
        }

        private void button_Cancelar_Click(object sender, EventArgs e)
        {
            if (button_Cancelar.Text == "Arranque")
            {
                button_Cancelar.Text = "Cancelar";
                TestDoEvents();
                progressBar_barrra_progreso.Value = 0; // Resetear progressBar a 0.
                label_Bytes_transmitidos.Text = "0";
            }
            else
            {
                if (alto == true)
                {
                    alto = false;
                }
                else
                {
                    alto = true;
                    button_Cancelar.Text = "Arranque";
                }
            }
        }
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Eleкtro

#5
Cita de: Meta en 22 Agosto 2017, 01:38 AM
Código (csharp) [Seleccionar]
progressBar_barrra_progreso.Value = 0; // Resetear progressBar a 0.

Lo correcto, tanto por estética del código fuente, como por rendimiento y seguridad del producto final, sería utilizar el método ProgressBar.Increment:

Código (csharp) [Seleccionar]
progressBar1.Increment(1);

De esta forma evitarías futuros posibles errores humanos como sería por ejemplo:
Código (csharp) [Seleccionar]
progressBar1.Maximum = 100;
progressBar1.Value = 101;

...Este código de arriba provocaría una excepción de tipo ArgumentOutOfRangeException, mientras que si usases el método ProgressBar.Increment podrías rebasar el valor máximo por accidente sin provocar ninguna excepción.

Ejemplo demostrativo:
Código (csharp) [Seleccionar]
progressBar1.Maximum = 100;
for (int x = 0; x <= 999; x++) {
progressBar1.Increment(1);
}





Cita de: Meta en 22 Agosto 2017, 01:38 AM
Código (csharp) [Seleccionar]
Application.DoEvents();

No sé si habrás tenido la oportunidad de leer lo que programadores profesionales siempre han opinado sobre el método Application.DoEvents, pero todas las opiniones escritas en la World Wide Web se podrian resumir brevemente en las siguientes palabras: "Application.DoEvents() is EVIL, do not use it." - y quien dijo eso tuvo mucha razón. No debes utilizar dicho método a menos que seas consciente de lo que hace y como lo hace intérnamente, sé que es una via de escape facil para solventar la respuesta o responsiveness de la interfáz de usuario, pero es que esa metodología conlleva muchas desventajas, y a día de hoy es prehistórica. Lo único que te debería importar es lo siguiente: al lo único que consigues llamando a ese método de forma continua dentro de un búcle, es disminuir el rendimiento (la velocidad) de tu programa y el algoritmo de copiado, y no lo estás disminuyendo un poco, sino MUCHO ( puedes hacer la prueba por ti mismo con y sin llamar a Application.DoEvents() ).

( Aquí te dejo una opinión del gran gurú Hans Passant: https://stackoverflow.com/a/5183623/1248295 )

En lugar de utilizar el método Application.DoEvents(), puedes utilizar esto otro método:
...De esta manera, las llamadas continuas a Application.DoEvents() se disminuirán en consideración, y con ello aumentará bastante el rendimiento de tus algoritmos donde tengas que llamar a Application.DoEvents(). Y por supuesto al usar esta alternativa/mejora, la interfáz de usuario seguirá siendo responsiva a los eventos de notificación de Click.

...Pero mucho mejor y más correcto que utilizar Application.DoEvents(), que como ya dije ES UNA METODOLOGÍA PREHISTÓRICA (aparte de peligrosa), sería recurrir a los instrumentos que .NET Framework nos proporciona hoy en día, me refiero a la programación asincrónica, ni más, ni menos. Si necesitamos interactuar con los elementos de control de una UI, entonces lo más adecuado sería utilizar el componente BackgroundWorker, puesto que está precisamente diseñado para llevar a cabo la interactuactuación con la UI, pero podemos utilizar la classe Task, o Thread. También es importante utilizar los métodos Control.BeginInvoke / Control.Invoke según las circunstancias. Hay varias maneras de llevarlo a cabo, depende del escenario / circunstancias.

Por último, te muestro un pequeño ejemplo gráfico:

       

PD: Ahora que lo pienso mejor, debería haber escrito "responive UI" en lugar de "app" en la imagen, pero bueh. Si, ya sé que me preocupo por tonterías, soy así de exquisito o perfeccionista... según se mire xD.

Saludos.