Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Alternar colores en dbgrid (https://www.clubdelphi.com/foros/showthread.php?t=71698)

Casimiro Notevi 05-01-2011 23:29:11

Cita:

Empezado por José Luis Garcí (Mensaje 386713)
Bueno siento ser pesado, pero con unos pequeños cambios os muestro lo que digo.

No, hombre, no eres pesado, al contrario, se agradece la idea, aunque no creo que me lo acepten de esa forma, pero por probar que no quede :)

José Luis Garcí 06-01-2011 17:55:02

Casimiro, puedes adaptar el mismo código, para 5 colores o para 2, cambiado solamente lo siguiente en el case

........................................C..O..L..O..R.......A......U..S..A..R
Color............terminación......Para 10.......Para 5...........Para 2
0------------------0-----------0----------0-------------0
1------------------1-----------1----------1-------------1
2------------------2-----------2----------2-------------0
3------------------3-----------3----------3-------------1
4------------------4-----------4----------4-------------0
5------------------5-----------5----------0-------------1
6------------------6-----------6----------1-------------0
7------------------7-----------7----------2-------------1
8------------------8-----------8----------3-------------0
9------------------9-----------9----------4-------------1


Ventajas de este sistema, permite un mayor control, ya que no descuadra el color, ya que el color es según el termino del Lote (asiento en tu caso y al subir o bajar no pierde el color.

Casimiro Notevi 06-01-2011 18:08:23

Cita:

Empezado por José Luis Garcí (Mensaje 386804)
Ventajas de este sistema, permite un mayor control, ya que no descuadra el color, ya que el color es según el termino del Lote (asiento en tu caso y al subir o bajar no pierde el color.

Creo que no termino de entenderlo, ¿te refieres a cambiar el color según el número de asiento?

roman 06-01-2011 18:23:38

Cita:

Empezado por Casimiro Notevi (Mensaje 386721)
Después de probar las distintas opciones aportadas por los compañeros, debo ecir que no funcionan "totalmente" bien... o yo no he sabido implementarlas, que todo puede ser.

Así que creo que la única opción es la del campo que indique el color o algo así.

No creo que funcione ninguna de las técnicas propuestas. Ja, ja, qué pesimista. Pero es que todas se basan en el "orden" en que se van pintando las celdas pero, en teoría, no es posible saber en qué orden se pintan. Dicho de otra forma, el pintado de celdas no necesariamente es secuencial sino que depende de muchos factores visuales que determinan cuáles celdas son las que requieren repintado. Por ello es que se usa el evento DrawColumnCell. Cuando la VCL detecta que una celda necesita repintarse, lanza el evento.

Por otra parte, la opción de un campo calculado que determina el coor con el que debe pintarse, pues me suena extraña. El valor de un campo calculado, normalmente, debe determinarse en términos de otros valores en el mismo registro, y si podemos usar valores en el mismo registro para saber de qué color hay que pintar, entonces no necesitamos el campo calculado sino simplemente hacer el cálculo en el evento DrawColumnCell.

// Saludos

Casimiro Notevi 06-01-2011 18:56:40

Entonces, ¿qué sugieres? :D
Que llevo tres días con esta tontería y no termina de ir bien, algo tan "simple" :S

Delphius 06-01-2011 19:41:49

No se que dirán ustedes pero creo que acabamos de encontrar el nuevo reto delphi :D

Yo digo que el gran maestros de maestros de centésimo dan Román nos ilustre ;) Yo no tener más neuronas. :o

Saludos,

roman 06-01-2011 20:00:41

Ja, ja. Yo no dije que tuviera la solución, simplemente comenté mi renuencia a creer en las ya existentes :D

Yo opino que el switch no funciona porque el pintado de celdas no necesariamente es secuencial. Sin embargo, esta técnica del switch podría usarse desde la consulta sql. Por ejemplo, en MySQL puedo hacer algo parecido a esto:

Código SQL [-]
set @asiento=0,@colorear=0;
select asiento, control, fecha, if (@asiento <> asiento, @colorear:=1-@colorear, @colorear) as colorear, @asiento:=asiento
from tabla
order by fecha, asiento, control

La columna "colorear" alterna entre 1 y 0 según cambia el valor del campo asiento, de manera que la condición en el evento DrawColumnCell se reduce a:

Código Delphi [-]
if DBGrid1.DataSource.DataSet.FieldByName('colorear').AsInteger = 1 then
  DBGrid1.Canvas.Brush.Color := clGreen;

Supongo que en Firebird también existen las variables de usuario así que podría hacerse algo similar.

// Saludos

Delphius 06-01-2011 20:13:37

¿Y que me dices de mi propuesta? Llevar una estructura que registre la distribución de pintado.

Yo para ahorrar espacio decía algo como:

HastaRegistro - Color
1 - Blanco
6 - Negro
8 - Blanco
...

Alterando esa idea se puede concebir una estructura de igual tamaño que la cantidad de registros:

RegistroNro - Color
1 - Blanco
2 - Negro
3 - Negro
...
6 - Negro
7 - Blanco
8 - Blanco

La idea es armar esta estructura analizando los registros. Cuando tenemos esta estructura ya podemos pintar el DBGrid, fila a fila en base a la evaluación del RecNo y comparandolo con RegistroNro de la estructura.

Si el evento DrawColumnCell se levanta a sus ganas, entonces forzemosle a decir, mira... tu correspondes al registro x, por tanto tu color es z.

Me dirán que es un desperdicio de memoria pero no veo otra manera.

Saludos,

roman 06-01-2011 20:21:46

Cita:

Empezado por Delphius (Mensaje 386824)
Me dirán que es un desperdicio de memoria pero no veo otra manera.

Sí, la que yo he puesto :p

Es que con tu idea hay que traerse todos los registros al cliente de una sóla vez.

// Saludos

José Luis Garcí 06-01-2011 20:36:55

Si casimiro, el color se asigna al asiento, en caso de lo que quieras es tener un Grid por colores pero por tipo de asiento (según tu post nº 1, normalmente están ordenados por fecha y no por asiento, esto funcionaría tal cual), en el otro caso, deberías usar dos variables globales, que compruebe en orden de carga si el valor del asiento cambia, asignamos primero el valor del nuevo asiento y en la segunda variable el color a o el b, lo elegimos cuando cambiamos alternando entre el a y el b, mientras tengamos el mismo número de asiento, seguimos con el mismo color al cambiar cambiamos el color.

Espero haberme explicado bien.

Delphius 06-01-2011 20:40:11

Pues, al comienzo no entendí tu idea roman. Ahora que la leo de nuevo ya le ví el truco.

¡Maestro!, me saco el sombrero. :eek: :)

Tengo la cabeza frita, no recuerdo bien si Firebird cuenta con variables de usuario y trabajar con un select. Pero la alternativa es generar un SP y allí si se puede trabajar cómodamente y aplicar lo que comentas.

Saludos,

roman 06-01-2011 20:43:20

¿Cómo sería con un procedimiento almacenado?

// Saludos

Aleca 06-01-2011 20:48:40

Cita:

Empezado por roman (Mensaje 386809)
....
Por otra parte, la opción de un campo calculado que determina el coor con el que debe pintarse, pues me suena extraña. El valor de un campo calculado, normalmente, debe determinarse en términos de otros valores en el mismo registro, y si podemos usar valores en el mismo registro para saber de qué color hay que pintar, entonces no necesitamos el campo calculado sino simplemente hacer el cálculo en el evento DrawColumnCell.

// Saludos

me parece que estos caminos no nos llevan a buen puerto, hay que replantearse la solución, a ver tenemos que encontrar la forma de que cada fila pueda tener el color para pintar y que no se cambie mientras nos movemos dentro de la grilla, el problema en la practica que veo es la posibilidad de tener muchos registros estariamos usando el tiempo en saber el color.
:confused::confused:
Casimiro, una pregunta, porque necesitas hacerlo de esta forma?

Saludos:)

roman 06-01-2011 20:53:10

Cita:

Empezado por Aleca (Mensaje 386836)
Casimiro, una pregunta, porque necesitas hacerlo de esta forma?

Quizá es muy simple mi respuesta pero yo diría que para poder distinguir fácilmente los grupos :)

// Saludos

Casimiro Notevi 06-01-2011 21:01:58

Pues sí, para separar los distintos asientos:



Dibujar es fácil, funciona perfecto con todos los ejemplos que han puesto todos los compañeros, el problema viene cuando te mueves por el grid arriba y abajo, llegas al final y al principio, etc.

El ejemplo de Román no he podido probarlo porque desconozco el tema de las variables de usuario en firebird, estoy buscando información al respecto.

Aleca 06-01-2011 21:05:37

Cita:

Empezado por roman (Mensaje 386839)
Quizá es muy simple mi respuesta pero yo diría que para poder distinguir fácilmente los grupos :)

// Saludos

lo preguntaba por que a lo mejor puede haber otra solución de acuerdo al objetivo que tenga.
Por las dudas...:confused::confused:
Saludos :)

Aleca 06-01-2011 21:09:33

a ver, otra pregunta tonta, puede haber muchos registros?
lo pregunto porque creo que hay que anclar el color de la fila con el registro.:confused:

Delphius 06-01-2011 21:14:26

El procedimiento almacenado para Firebird sería algo como este (probado en una tabla de prueba que tengo):

Código SQL [-]
SET TERM ^ ;

CREATE PROCEDURE PINTAR_TABLA 
RETURNS (
    NEW_COLOREAR INTEGER,
    NEW_FECHA DATE,
    NEW_NOMBRE VARCHAR(30),
    NEW_ID INTEGER)
AS
DECLARE VARIABLE VAR_COLOREAR INTEGER;
DECLARE VARIABLE VAR_ID INTEGER;
begin
  /* Procedure Text */
  var_colorear = 0;
  var_id = 0; /* sería el campo asiento */
  for select ID, NOMBRE, FECHA from tabla1 order by ID, FECHA, NOMBRE
  into :new_id, :new_nombre, :new_fecha
  do
    /* calculamos */
    begin
      if (var_id <> :new_id) then var_colorear = 1 - var_colorear;
      new_colorear = var_colorear;
      var_id = :new_id;
      suspend;
    end
end
^

SET TERM ; ^

GRANT SELECT ON TABLA1 TO PROCEDURE PINTAR_TABLA;

GRANT EXECUTE ON PROCEDURE PINTAR_TABLA TO SYSDBA;

Saludos,

Delphius 06-01-2011 21:22:33

Basicamente la idea es que el campo "Colorear" alterne entre 1 y 0. Se va recorriendo la consulta ordenada por fecha y asiento almacenando los valores en una variable. Si resulta ser que el valor del asiento del actual registro es distinto al de la variable se altera el valor del campo colorear por su "negado". En otro caso queda el valor anterior.

Luego, cuando se va pintando el DBGrid, se evalúa el valor del campo Colorear y si 1 o 0 se establece un color o otro y se pinta.

Saludos,

Delphius 06-01-2011 21:50:54

Ha... y como PLUS :) , la técnica que me inspiró roman da incluso para trabajar con más de dos colores.

Siendo N la cantidad de colores, podemos alternar cíclicamente los colores haciendo algo como:

Código Delphi [-]
ColorElegido = Color mod N;

Siendo Color una variable que se incrementa cuando se cumple la condición:
Código Delphi [-]
(Asiento <> var_Asiento)

Espero que se entienda la idea ;)

De ese modo tendremos que el valor del hipotético campo "Colorear" irá alternando desde 0 a N-1 cada vez que detecte un nuevo asiento.

EDITO:
Esto se ha convertido en un monólogo :D

Saludos,


La franja horaria es GMT +2. Ahora son las 16:35:00.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi