2008-07-31 10 views
543

Quiero usar una barra de seguimiento para cambiar la opacidad de un formulario.Al aplicar opacidad a un formulario, ¿debemos usar un valor decimal o doble?

Este es mi código:

decimal trans = trackBar1.Value/5000; 
this.Opacity = trans; 

Cuando construyo la aplicación, se da el siguiente error:

Cannot implicitly convert type 'decimal' to 'double' .

He intentado utilizar trans y double pero entonces el control no funciona. Este código funcionó bien en un proyecto anterior de VB.NET.

+8

Además, decimal no puede representar tan ancho como un valor doble. El decimal solo puede subir a +/- 7.9228162514264337593543950335E + 28; mientras que un Doble puede ir hasta +/- 1.79769313486232E + 308 – TraumaPony

Respuesta

391

una conversión explícita para duplicar como esto no es necesario:

double trans = (double) trackBar1.Value/5000.0; 

identifica la constante como 5000.0 (o como 5000d) es suficiente:

double trans = trackBar1.Value/5000.0; 
double trans = trackBar1.Value/5000d; 
53

Suena como this.Opacity es un doble valor, y al compilador no le gusta que trates de meter un valor decimal en él.

112

Una respuesta más genérica para la pregunta genérica "Decimal vs doble?": decimal para los cálculos monetarios para preservar la precisión, doble para los cálculos científicos que no se deje afectados por pequeñas diferencias. Dado que Double es un tipo nativo de la CPU (la representación interna se almacena en base 2), los cálculos realizados con Double funcionan mejor que Decimal (que se representa en base 10 internamente).

55

En mi opinión, es conveniente ser lo más explícito posible. Esto agrega claridad al código y ayuda a los demás programadores que eventualmente lo puedan leer.

Además de (o en lugar de) agregar un .0 al número, puede usar decimal.ToDouble().

Éstos son algunos ejemplos:

// Example 1 
double transperancy = trackBar1.Value/5000; 
this.Opacity = decimal.ToDouble(transperancy); 

// Example 2 - with inline temp 
this.Opacity = decimal.ToDouble(trackBar1.Value/5000); 
74

Su código funcionó bien en VB.NET, ya que implícitamente hace ningún moldes, mientras que C# tiene tanto los implícitos y explícitos.

En C# la conversión de decimal a doble es explícita a medida que pierde precisión. Por ejemplo, 1.1 no se puede expresar con precisión como un doble, pero puede hacerlo como un decimal (ver "Floating point numbers - more inaccurate than you think" por el motivo).

En VB se añadió la conversión para usted por el compilador:

decimal trans = trackBar1.Value/5000m; 
this.Opacity = (double) trans; 

Eso (double) tiene que ser declarado explícitamente en C#, pero puede haber implicado en más del compilador 'perdón' de VB.

73

¿Por qué estás dividiendo por 5000? Simplemente configure los valores Mínimo y Máximo del TrackBar entre 0 y 100 y luego divida el Valor por 100 para el porcentaje de Opacidad.El mínimo 20 ejemplo siguiente impide la forma de convertirse en completamente invisible:

private void Form1_Load(object sender, System.EventArgs e) 
{ 
    TrackBar1.Minimum = 20; 
    TrackBar1.Maximum = 100; 

    TrackBar1.LargeChange = 10; 
    TrackBar1.SmallChange = 1; 
    TrackBar1.TickFrequency = 5; 
} 

private void TrackBar1_Scroll(object sender, System.EventArgs e) 
{ 
    this.Opacity = TrackBar1.Value/100; 
} 
+3

¿Esto no resolvería el problema? En lugar de un problema con '5000', OP tendría un problema con' 100'? – jww

45

Debe utilizar 5000.0 en lugar de 5000.

56

Tiene dos problemas. En primer lugar, Opacity requiere un valor doble, no decimal. El compilador le dice que si bien hay una conversión entre decimal y doble, es una conversión explícita que debe especificar para que funcione. El segundo es que TrackBar.Value es un valor entero y dividir un int por un int da como resultado un int sin importar el tipo de variable que le asigne. En este caso hay un molde implícito de int a decimal o double, porque no hay pérdida de precisión cuando haces el reparto, por lo que el compilador no se queja, pero el valor que obtienes es siempre 0, presumiblemente, ya que trackBar.Value es siempre menos de 5000. La solución es cambiar su código para usar double (el tipo nativo para Opacity) y hacer aritmética de coma flotante haciendo explícitamente a la constante un doble, lo que tendrá el efecto de promover la aritmética, o lanzar trackBar.Value para duplicar , que hará lo mismo, o ambos. Ah, y no necesitas la variable intermedia a menos que se use en otro lado. Mi suposición es que el compilador lo optimizaría de todos modos.

trackBar.Opacity = (double)trackBar.Value/5000.0; 
44

La propiedad Opacity es de tipo double:

double trans = trackBar1.Value/5000.0; 
this.Opacity = trans; 

o simplemente:

this.Opacity = trackBar1.Value/5000.0; 

o:

this.Opacity = trackBar1.Value/5000d; 

en cuenta que estoy usando 5000.0 (o 5000d) para forzar una división doble porque trackBar1.Value es un número entero y realizaría una división entera y el resultado sería un número entero.

42

Suponiendo que está usando Windows Forms, Form.Opacity es de tipo double, por lo que debe utilizar:

double trans = trackBar1.Value/5000.0; 
this.Opacity = trans; 

A menos que necesite el valor en otro lugar, es más fácil de escribir:

this.Opacity = trackBar1.Value/5000.0; 

La razón por la el control no funciona cuando cambiaste tu código para simplemente ser un doble porque tenías:

double trans = trackbar1.Value/5000; 

que interpretó el 5000 como un entero, por lo que su valor trans siempre fue cero. Al convertir explícitamente el valor numérico en coma flotante agregando el .0, el compilador ahora puede interpretarlo como un doble y realizar el cálculo adecuado.

38

La mejor solución es:

this.Opacity = decimal.ToDouble(trackBar1.Value/5000); 
37

Desde Opacity es un valor doble, yo sólo uso una doble desde el principio y no echo en absoluto, pero asegúrese de usar un doble al dividir por lo que don 't desata alguna precisión

Opacity = trackBar1.Value/5000.0; 
31
this.Opacity = trackBar1.Value/5000d; 
Cuestiones relacionadas