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)

duilioisola 07-01-2011 11:11:44

Ahora estoy pensando en agregar una variable más:
CampoOrden para saber por qué campo está ordenado el DataSet y así poder compararlo con la variable ValorAnterior.

Código Delphi [-]
{Global al DataModule CampoOrden string}

procedure TDMMayor.xMayorCalcFields(DataSet: TDataSet);
begin
   {El campo calculado se inicializa a 0. Solo recalculo si es este valor}
   {ValorAnterior siempre guarda el valor del ultimo registro}

   {Si todavía no he establecido el valor del campo calculado}
   if (DataSet.FieldByName('SOMBRA').AsInteger = 0) then
   begin
      {Si el valor cambia, alterno el valor de Sombra}
      if (ValorAnterior <> DataSet.FieldByName(CampoOrden).AsString) then
      begin
         Sombra := not Sombra;
         ValorAnterior := DataSet.FieldByName(CampoOrden).AsString;
      end;
      
      if (Sombra) then
         DataSet.FieldByName('SOMBRA').AsInteger := 1
      else
         DataSet.FieldByName('SOMBRA').AsInteger := 2;
   end;
end;

procedure Ordenar(Orden : string);
begin
   CampoOrden := Orden;
   {Cambiar ORDER BY de SelectSQL}
   xMayor.SelectSQL.Text := SLQBase; {select * from ... where ...}
   xMayor.SelectSQL.Text := xMayor.SelectSQL.Text + ' ORDER BY ' + CampoOrden;
end;

José Luis Garcí 07-01-2011 12:33:24

Casimiro he subido al Ftp del club lo que te comentaba en este caso tienes las opciones de 2 o 5 colores y de usar por asiento o por cambio de asiento, con control por variables, pero en este último caso, pasa lo que comentas de perder el color y demás, pero en el otro no.

En el primer caso, te recomendaría el usar un color por terminación del 0 al 9, pero te he expuesto el ejemplo a dos colores y a cinco.

En la misma carpeta tienes la base de datos Firebird 2.0 ten en cuenta que tendrás que cambiar la ruta para acceder a ella.

El Archivo es Prueba Grid Coloreado.zip y pesa unos 800K

Espero te pueda echar una mano

Casimiro Notevi 07-01-2011 13:24:39

Bueno, en principio... ¡¡¡haya paz!!!, es lo único que he pedido a los reyes magos, así que ayer no encontré ningún regalo junto al árbol de navidad :(, entonces supongo que se cumplirá mi deseo :D. Todas las propuestas me parecen estupendas, las valoro muchísimo y no desmerezco ninguna, al contrario, es algo que agradezco muchísimo porque sé el tiempo que lleva pensarlo, probarlo, comentarla aquí y defenderla :)
MUCHÍSIMAS GRACIAS A TODOS, sin excepción.


Ante tanta avalancha de soluciones posibles... ¡¡¡no me da tiempo de probarlas todas!!! :D, porque tengo que implementarlas bien en mi código para decidir si realmente no terminan de funcionar bien o es que simplemente yo no lo he implementado correctamente. Y no me gustaría desechar ninguna propuesta sugerida por vosotros que resulte que sí funcione correctamente y que sea yo el culpable de no haberla probado bien.

Cita:

Empezado por Chris (Mensaje 386884)
Solo una pregunta. Independientemente del número en que se inicie el valor del campo ASIENTO, ya sea 5,6,7, etc. los números siempre serán consecutivos? Si fuese así, puedes utilizar el valor del número más bajo. Hacer una resta y del residuo calcular si es par o impar. Par un color, impar otro color.

Tan sólo aclarar que la consulta, después de que el usuario ha escogido una serie de filtros más o menos amplios, se trae los registros ordenados por: fecha, numeroasiento, numerolinea. Y el campo que hay que controlar para el cambio de color es numeroasiento.
Un asiento tiene sus lineas todos con la misma fecha, los asientos normalmente estarán ordenados también, aunque no siempre. Las líneas siempre. Lo principal es que los asientos están agrupados.

---fecha---asiento---linea---
05.01.2011----20-------1-----
05.01.2011----20-------2-----
05.01.2011----20-------3-----
05.01.2011----32-------1-----
05.01.2011----32-------2-----
08.01.2011----28-------1----- <-- en este caso no está ordenado por asiento
08.01.2011----28-------2-----
08.01.2011----29-------1-----
08.01.2011----29-------2-----
08.01.2011----29-------3-----
-----------------------------

Y repito, el problema no es pintarlos cuando se se hace el select y se presenta en el grid, el problema viene después cuando te mueves por el grid con teclas o ratón.

Casimiro Notevi 07-01-2011 13:54:41

Cita:

Empezado por José Luis Garcí (Mensaje 386895)
[..] En la misma carpeta tienes la base de datos Firebird 2.0 ten en cuenta que tendrás que cambiar la ruta para acceder a ella.

¿Puedes poner el metadata para crear la BD yo mismo?, o haces un backup transportable para que yo la restaure, es que tengo fb1.5 y 2.1. Y con ninguna de ellas puedo acceder a esa BD.

Chris 07-01-2011 18:06:01

No pensaba en contestarte xq era desvirtuar el hilo. Pero has sido demaciado tosco y necesito contestar tus desagradables palabras.

Cita:

Empezado por Delphius (Mensaje 386887)
Y si me molestó, porque lanzaste un comentario a modo de indirecta a todo aquella persona que ha propuesto una ALTERNATIVA. Repito: ALTERNATIVA, no una solución que sea perfecta, bonita y que te caiga bien a tus propios gustos.

Estamos presentando alternativas, no sabíamos que te tenía que caer bien a vos.

Creo que lo que a tí te molesta es una opinión contraria a tus ideas. No critique a cada una de las personas que propuso una solución, hay muchas soluciones propuestas si te fijas en todo el hilo. Critiqué, no solo la solución propuesta por Roman y desarrollada por tí, sino todas las que usen de muleta a la base de datos. Las critico (en el mejor sentido de la palabra) y lo seguiré haciendo. Creo que mi critica no fue en mal modo, si te fijas, eres el único que la ha tomado a mal. Te has ahogado en un vaso de agua sinceramente.


Cita:

Empezado por Delphius (Mensaje 386887)
¿Y no crees que Casi ha pedido ayuda y aquí entre todos, cada uno desde su lugar hizo o está haciendo un esfuerzo?

Cita:

Empezado por Chris (Mensaje 386883)
... Si tienes problemas para pintar la GUI, pídele ayuda a otro programador, no a la base de datos.

Sabes leer, pero no interpretar. Casimiro hizo lo correcto, vino a pedir ayuda a otros programadores.

Cita:

Empezado por Delphius (Mensaje 386887)
Tu pretendes tildar a Casi y a los demás como incompetente. Evita esas indirectas molestas... aqui ninguno viene con aires de traer la superioridad...

Si así lo quieres ver desde tu distorsionada perspectiva.... allá tú. El que se pretende con aires de superioridad eres tú. No toleras la más mínima critica a tus opiniones o en este caso, a tu manera de solucionar las cosas.


Cita:

Empezado por Delphius (Mensaje 386887)
Sabes que existe algo llamado KISS... a lo siento... tu prefieres seguir rompiéndote la cabeza y no intentar darle un giro a tus ideas. Bien por ti, si quieres seguir complicándote.

No programo desde ayer, sé que es KISS. Yo creo que lo único que sabes es que KISS es la abreviación de "Keep it simple stupid", más no sabes lo que eso conlleva. Puedes aprenderlo aquí.

Cita:

Empezado por Delphius (Mensaje 386887)
No podemos asegurar que sea N segundos, quizá sea N/2 lo cual sería un factor considerable. Y te digo que en ocasiones es preferible que se la aguanten un poquito antes que tener un código que podría tener la posibilidad de estallar en un futuro y ser inestable en cuanto se añadan nuevas mejoras o adiciones.

¿Y como sabes y estás tan seguro que tan deficiente eres? ¿Que carajos sabes de los factores que inducen a la perfomance a la que verá sometido el sistema de Casimiro? Quizá esta consulta la use unas pocas personas, muy pocas veces al día, quizá tenga un buen servidor...
Hay más que mirar, y no necesariamente habrá una perdida considerable de perfomance.

Si no sabías, hay otra regla en el desarrollo de software: NO DES NADA POR SENTADO. Deberías tenerla siempre en cuenta porque es una de la más importantes.

Cita:

Empezado por Delphius (Mensaje 386887)
Si, sigamos con el hilo... que no tiene sentido discutir, menos con alguien que pretende ponerle punto final a un debate de ideas.

Creo que en esa frase te estás reflejando tú. Te juro que no me siento aludido.

Cita:

Empezado por Delphius (Mensaje 386887)
Te aviso además, que no fui el iniciador y motivador principal de la solución por el lado de la base de datos... fue román, si tienes algo que decir y objetar crítica a él. Yo solamente seguí su planteo y propuse una ALTERNATIVA.

Leí la solución propuesta por Roman un minuto después que la propuso. Sé que el tuvo la idea. Pero solo dio una idea, no dijó que fuera la solución. Así lo hemos hecho todos aquí, eso creo. Si tengo algo que decir y objetar será a esta idea, no a él.

Ya sinceramente..... NEEEEXT!!!

Chris 07-01-2011 18:08:59

Cita:

Empezado por Casimiro Notevi (Mensaje 386900)
¿Puedes poner el metadata para crear la BD yo mismo?, o haces un backup transportable para que yo la restaure, es que tengo fb1.5 y 2.1. Y con ninguna de ellas puedo acceder a esa BD.

También espero la metadata. Ya esto se volvió un reto. Es lo que me detiene a probar un código productivo, que no tengo datos para hacer las pruebas. Pero sin embargo, creo que el mejor podría proporcionar una base de donde partir es casimiro. Digo, danos una tierra fértil (una GUI y datos adecuados al problema) para hacer fertilizar ideas.

roman 07-01-2011 18:25:16

Hola,

Concuerdo con Chris en no usar al servidor de datos como muletilla para lo que es GUI. En ningún momento tomé sus palabras como una ofensa.

Por otra parte, si buen concuerdo, como dije, con Chris; también creo que hay veces en que a falta de una buena solución hay que hacer uso de los recursos de que dispongamos aunque no sean los ideales.

Hasta el momento creo que ninguna de las soluciones puramente GUI funciona al 100% (*) y entre traer todos los registros al cliente o usar un SP, prefiero lo segundo (aunque yo, en lo personal prefiero mi solución je, je).

Creo que hay rejillas de terceros que manejan esto de forma sencilla, pero también hay que tener en cuenta lo del cero presupuesto que menciona Casimiro. Así que, un pequeño tiempo extra en la consulta bien compensa la falta de presupuesto.

De todas formas, si se encuentra una solución puramente GUI será mucho mejor.





(*) He estado probando la solución de duilioisola pero también tiene sus bemoles. Por alguna razón, al dar click sobre la barra de desplazamiento vertical los colores se alternan (lo que estaba sombreado deja de estarlo y viceversa), lo que produce un efecto feo. Además, si la selección esta en ciertos registros, dicho click produce un sombreado incorrecto a partir de la selección.

// Saludos

Casimiro Notevi 07-01-2011 19:15:05

Bueno, aquí he puesto un ejemplo sencillo para poder trabajar sobre él.
No recuerdo de qué compañero es, pero tiene el mismo inconveniente, en según qué casos alterna los colores incorrectamente.
Yo ya estoy pensando que es un fallo mío, no sé, en fín, ahí está.
He añadido un sql para crear la BD por si acaso tenéis una versión distinta a la FB2.1 y además se le añaden un montón de registros de pruebas.
Concretamente las pruebas que estoy haciendo son con fechas 16/12/2010, luego el día 17, luego el 18 y así en adelante, ninguna de las propuestas presentadas ha llegado a presentar correctamente los datos cuando la fecha es 19/12/2010, si vamos al último registro con las flechas y luego subimos hasta el principio... los colores se han alternado. Lo que era claro se convierte oscuro y lo oscuro se convierte en claro.

José Luis Garcí 07-01-2011 19:18:44

Perdonar por no responder antes, pero tuve que salir a llevar a mi hija a casa de unas amigas.


En cuanto a la metadata he probado en el Ib Expert y lo que me saca ee con todos los registros, así que opte por imprimir la estructura a un PDF, recordar que la base de datos en este caso es DEPRUBA.FDB, con una única tabla MOVIMIENTOS.

En Cuanto a los Registros no os preocupéis ya que el programa tiene un botón que crea 100 registros aleatorios cada vez que lo pulséis.

Casimiro Notevi 07-01-2011 19:19:12

Cita:

Empezado por roman (Mensaje 386924)
[..]
Hasta el momento creo que ninguna de las soluciones puramente GUI funciona al 100% (*) y entre traer todos los registros al cliente o usar un SP, prefiero lo segundo (aunque yo, en lo personal prefiero mi solución je, je).

Realmente es muy ingeniosa, qué pena que firebird no permita hacer algo así, al menos yo no sé cómo hacerlo.
Sí, vaaaaleeee... mysql también tiene cosas buenas :D

José Luis Garcí 07-01-2011 19:19:30

1 Archivos Adjunto(s)
Lo siento se me olvido el archivo aquí esta.

José Luis Garcí 07-01-2011 19:31:42

Para los que no quieran bajar el ejemplo aquí dejo una vista del ejemplo con el botón del que hablaba antes enmarcado.


Casimiro Notevi 07-01-2011 19:41:52

Soy un manazas :D
Lo he trasteado un poco y han aparecido dos grupos de asientos juntos y con el mismo color.


roman 07-01-2011 19:52:58

Cita:

Empezado por Casimiro Notevi (Mensaje 386927)
He añadido un sql para crear la BD

¿Los campos de interés son NUMEROASIENTO, LINEAASIENTO Y FECHAASIENTO? Digo, porque no concuerdan exactamente con los que habías mencionado.

// Saludos

Casimiro Notevi 07-01-2011 20:04:44

Cita:

Empezado por roman (Mensaje 386934)
¿Los campos de interés son NUMEROASIENTO, LINEAASIENTO Y FECHAASIENTO? Digo, porque no concuerdan exactamente con los que habías mencionado.
// Saludos

Sí, el usuario pide la fecha (o entre qué fechas) y se ordena por fecha, numeroasiento, lineaasiento.
El campo que debe cambiar de color es numeroasiento.
La imagen que he puesto en el post de antes es del programa de José Luis Garcí.

roman 07-01-2011 20:15:59

1 Archivos Adjunto(s)
A ver, está bien ser realistas pero para efectos de probar lo que nos interesa me parece que podrías haber omitido unos cuantos campos :p

Aquí pongo un extracto de datos para los que quieran usarlo :)

// Saludos

roman 07-01-2011 20:22:15

Cita:

Empezado por Casimiro Notevi (Mensaje 386933)
Soy un manazas :D
Lo he trasteado un poco y han aparecido dos grupos de asientos juntos y con el mismo color.

No es que seas un manazas, es que el código dice:

Código Delphi [-]
case UlDigit(StrToInt(DataSource1.DataSet.FieldByName('ASIENTO').value)) of
    0 :ColorElegido:=ColorA;
    1 :ColorElegido:=ColorB;
    2 :ColorElegido:=ColorC;
    3 :ColorElegido:=ColorD;
    4 :ColorElegido:=ColorE;
    5 :ColorElegido:=ColorA;
    6 :ColorElegido:=ColorB;
    7 :ColorElegido:=ColorC;
    8 :ColorElegido:=ColorD;
    9 :ColorElegido:=ColorE;
end;

o sea, asigna el mismo color a los asientos con terminaciones 0 y 5.

La verdad no termino de entender cómo funciona el método que propone José Luis. La probabilidad de que existan grupos de asientos contiguos con el último dígito igual creo que puede ser muy alta.

// Saludos

ElKurgan 07-01-2011 20:25:57

Dejando aparte el tema, me parece que aqui pasa una cosa curiosa:

1.- Todos nos decimos "novatos"
2.- Pero todos nos enfadamos si no se usan nuestras soluciones
3.- A una petición de ayuda de Casimiro, algunos han empezado guerras particulares...

Yo creo que un poco de humildad en todos nosotros nos hace ser un poco mejores. No olvidar que este foro es lo que es gracias a TODOS los que participamos en él

Saludos

Casimiro Notevi 07-01-2011 20:28:22

Cita:

Empezado por roman (Mensaje 386937)
A ver, está bien ser realistas pero para efectos de probar lo que nos interesa me parece que podrías haber omitido unos cuantos campos :p
Aquí pongo un extracto de datos para los que quieran usarlo :)
// Saludos

Perdón, es que quise que se pareciera lo más posible a la realidad :D

José Luis Garcí 07-01-2011 20:34:57

Como dice Roma no estas equivocado Casimiro, la asignación es para cinco y por eso te pasa el que dos tenga el mismo color, en el caso de los diez dígitos las probabilidades serían menor, claro se puede hacer para cien, mil, etc, pero creo que aun así las probabilidades de que ocurriese siempre existirían. Lo que te expongo es sólo una idea, podrías aplicarle a esta para cinco,para la de dos o la de diez, la siguiente situación si color a asignar es igual ala variable global colorelegido y el valor del campo ASIENTO diferente a la variable global Asiento, dibujo una linea en la parte superior de la presente fila para distinguir mejor los diferentes asientos, aún con el mismo color.

De lo único que estoy seguro es de que no se te desplazarán los colores.

La idea es que quedara así, más o menos



Casimiro Notevi 07-01-2011 20:42:08

Entonces me temo que en ese caso no me vale la propuesta, la condición es que no existan asientos juntos con colores iguales, pero tampoco pueden existir varios colores que confundan al usuario, en principio sólo dos colores.
Es lo que me han pedido, por mí se los presento todos en blanco y negro y se acabó, que el usuario se fije bien :D


A ver, eso de la línea parece interesante, ¿cómo lo haces?

cloayza 07-01-2011 20:47:19

Revisando todos los post se me ocurrio hacer lo siguiente...

Me recorde que cuando en la grilla uno realiza seleccion de registros internamente se utiliza un TList para almacenar los bookmark de los registros seleccionados, debido a eso pense en utilizar un TStrings para almacenar la informacion que se requiere por cada registro.

Este es el resultado, tome el codigo del amigo duilioisola y le hice algunos cambios...

Código Delphi [-]
 public
    { Public declarations }
    Sombra:Boolean;
    List:TStrings;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
   index:Integer;
begin
      with TDBGrid(Sender) do
      begin
         if (gdFocused in State) then //Si tiene el foco
         begin
            Canvas.Font.Color := clWhite;
            Canvas.Brush.Color := clHighlight;
         end
         else
         begin
//Busco el Asiento en el List            
Index:=List.IndexOf(DataSource.DataSet.FieldByName('ASIENTO').AsString);
//Obtengo el valor boolean para realizar la pregunta...
            if Boolean(List.Objects[index]) then
            begin
               Canvas.Font.Color := clBlack;
               Canvas.Brush.Color := clYellow;
            end
            else
            begin
               Canvas.Font.Color := clBlack;
               Canvas.Brush.Color := clInfoBk;
            end;
         end;
         DefaultDrawColumnCell(Rect, DataCol, Column, State);
      end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
     List:=TStringList.Create; //Creo el list que almacenara los datos de cada rfegistro...
     
     Table1.Active:=True;
end;

procedure TForm1.Table1AfterOpen(DataSet: TDataSet);
begin
   Sombra := True;
end;

procedure TForm1.Table1CalcFields(DataSet: TDataSet);
var
   Index:Integer;
begin
      //Verifico si el Asiento ya esta en la List...
     Index:=List.IndexOf(DataSet.FieldByName('ASIENTO').AsString);
     if Index=-1 then
     begin
          //AL no encontrase en List lo agrego con el valor booleano de sombra...
          List.AddObject(DataSet.FieldByName('ASIENTO').AsString, Pointer(Sombra) );
          Sombra := not Sombra;
     end;
end;

Por supuesto faltan las validaciones...
Saludos cordiales

José Luis Garcí 07-01-2011 20:50:09

Casimiro, la verdad es una idea no la he llevado a la practica, pero me imagino que si la dibujas en el grid directamente te puede pasar que desaparezca al moverse como te ocurre en los colores, más bien pienso que seria añadirle un nuevo campo no visible al grid, y cada vez que ocurra la condición que te comentaba marco la casilla.

De todas maneras, piensa que por el sistema de asignación de color sin anclarlo a una condición estática (en este caso el número de asiento), te pueden desaparecer los colores al moverse el Grid.

cloayza 07-01-2011 20:58:17

Aqui incorporando muchos colores...
Código Delphi [-]
    Sombra:Boolean;
    List:TStrings;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
   index:Integer;
begin
      with TDBGrid(Sender) do
      begin
         if (gdFocused in State) then //Si tiene el foco
         begin
            Canvas.Font.Color := clWhite;
            Canvas.Brush.Color := clHighlight;
         end
         else
         begin
            {Sombra puede ser 1 o 2. Si está a 0 no esta establecido}
            Index:=List.IndexOf(DataSource.DataSet.FieldByName('ASIENTO').AsString);

            Canvas.Font.Color := clBlack;
           Canvas.Brush.Color := TColor(List.Objects[index]);

         end;
         DefaultDrawColumnCell(Rect, DataCol, Column, State);
      end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
     List:=TStringList.Create;
     Table1.Active:=True;
end;

procedure TForm1.Table1AfterOpen(DataSet: TDataSet);
begin
   Sombra := true;
end;

procedure TForm1.Table1CalcFields(DataSet: TDataSet);
var
   Index:Integer;
   fColor:TColor;
begin
     Index:=List.IndexOf(DataSet.FieldByName('ASIENTO').AsString);
     if Index=-1 then
     begin
          fColor:=RGB(Random(205),Random(205),Random(205));
          List.AddObject(DataSet.FieldByName('ASIENTO').AsString, Pointer(fColor)); //Sombra) );
          Sombra := not Sombra;
     end;
end;

Chris 07-01-2011 21:24:57

Bueno creo que ya tengo una primera alternativa...

Se trata de la mejora del código que ofrecí anteriormente. Solucionando sus problemas. Casimiro tendrá que revisar lots cambios hechos con respecto al programa que el subió hace unas horas.

Aquí el archivo que he subido.

Saludos,
Chris

Chris 07-01-2011 21:32:44

Este es el código:
Código Delphi [-]
procedure TForm24.gr1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
    background_colors: array[0..1] of TColor = (clYellow, clWhite);
var
    BackgroundColor: TColor;
begin
if (UltimoValor > qr1.FieldByName('NUMEROASIENTO').Value) then
begin
    if Pos(Format('-%s-', [qr1.FieldByName('NUMEROASIENTO').Value]), GrupoImpar) > 0 then
        BackgroundColor := background_colors[1]
    else
        BackgroundColor := background_colors[0];
end
else
begin
    if qr1.FieldByName('NUMEROASIENTO').Value <> UltimoValor then
            BoolSwitch := (not BoolSwitch);

        BackgroundColor := background_colors[Integer(BoolSwitch)];
        UltimoValor := qr1.FieldByName('NUMEROASIENTO').Value;
end;

if not (gdSelected in State) then
    TDBGrid(Sender).Canvas.Brush.Color := BackgroundColor;

TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);

if not (UltimoValor > qr1.FieldByName('NUMEROASIENTO').Value) then
    if (BoolSwitch) and (Pos(Format('-%s-', [qr1.FieldByName('NUMEROASIENTO').Value]), GrupoImpar) = 0) then
        GrupoImpar := (GrupoImpar + Format('-%s-', [qr1.FieldByName('NUMEROASIENTO').Value]));
end;

Cada vez que se hace la consulta hay que reiniciar las variables globales (UltimoValor, GrupoImpar, BoolSwitch) de esta forma:
Código Delphi [-]
  // inicializar los datos del control de grupo
  UltimoValor := 0;
  GrupoImpar := '';
  BoolSwitch := False;

No es un código perfecto. Obviamente se puede obtimizar un poco, de hecho creo que deberían tomarlo tipo pseudocodigo. Pero en mis pruebas ha funcionado según los requerimientos que le entiendo a casimiro. Cualquier inconveniente, pues dejadlo saber.

Saludos,
Chris

Chris 07-01-2011 21:39:47

De última hora he notado que si los registros no traen ningún tipo de orden en NUMEROASIENTO, el código que compartí hace unos minutos no funciona a cómo debería hacerlo. Vamos a trabajar en ello. Ya veremos una solución, nada más que parece no estar nada fácil :/

rgstuamigo 07-01-2011 21:41:42

Para tener en cuenta
 
Cita:

Empezado por Casimiro Notevi (Mensaje 386897)
...
Y repito, el problema no es pintarlos cuando se se hace el select y se presenta en el grid, el problema viene después cuando te mueves por el grid con teclas o ratón.

A mi me late que la solucion a tu problema ya ha sido resuelta con tanta alternativa que te han dado ;), pero nada mas se han olvidado de mencionarte algo que es lo siguiente:
Por experiencia propia (y no solo me ha pasado a mi, sino tambien a muchos ) que cuando utilizamos el evento OnDrawColumnCell del DBGrid para por ejemplo pintar algunas filas o celdas del Grid, por algunas extraña razon(Que tengo que invetigarla mas a fondo) al mover el scroll (movernos por los registros)del DBGrid ya sea con el mouse o con el teclado, Windows no dibuja por completo el DBGrid,es decir, pareciera que tiene un comportamiento extraño, por eso es que quizas te ha parecido que las soluciones que te han propuesto no te funcionan bien;).
Para solucionar ese problema y hacer que windows redibuje el DBGrid cada ves que te muevas por los registros, es necesario llamar al método Invalidate del DBGrid en algun evento específico;), por ejemplo yo utilizo el evento OnDataChange del DataSouce al que está enganchado el DBGrid para hacer el repintado ya que lo veo el más adecuado para hacerlo.;)
Código Delphi [-]
procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
begin
DBGrid1.Invalidate; //<- Hago que mi DBGrid se redibuje, eso implica que
             // internamente se ejecuta el evento OnDrawColumnCell del DBGrid
end;
Espero haberte aclarado un poco el panorama.;)
Saludos...:)

Casimiro Notevi 07-01-2011 22:17:51

Cita:

Empezado por Chris (Mensaje 386947)
Bueno creo que ya tengo una primera alternativa...Chris

Creo que no vale, el problema es que almacena en un string los números que ya ha presentado para saber con qué color presentarlo, para ello hay que recorrer desde el principio hasta el final todos los registros. Si por ejemplo vas directamente al último con ctrl+fin entonces no guarda esos valores y no puede pintarlos.

roman 07-01-2011 22:31:53

No sé si sirva para esto, pero lo más parecido que he encontrado en Firebird para las variables de usuario de MySQL es RDB$SET_CONTEXT() y RDB$GET_CONTEXT().

Podrías probar a ver si funcionan similarmente.

// Saludos

cloayza 07-01-2011 22:32:17

Una pequena optimizacion de codigo que propuse anteriormente.

Código Delphi [-]
 Sombra:Boolean;
    List:TStrings;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ESTE ES EL CODIGO QUE SE REQUIERE...}
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
   index:Integer;
   fColor:TColor;
begin
      if Not Assigned(List) then
         List:=TStringList.Create;

      with TDBGrid(Sender) do
      begin
         if (gdFocused in State) then
         begin
            Canvas.Font.Color := clWhite;
            Canvas.Brush.Color := clHighlight;
         end
         else
         begin
              Index:=List.IndexOf(DataSource.DataSet.FieldByName('ASIENTO').AsString);
              if Index=-1 then
              begin
                   if Sombra then fColor:=clYellow  else fColor:=clInfoBk;
{Para usar multicolores aleatorios descomentar esta linea...}
                   //fColor:=RGB(Random(205),Random(205),Random(205));

                   index:=List.AddObject(Datasource.Dataset.FieldByName('ASIENTO').AsString, Pointer(fColor));

                   Sombra := not Sombra;
              end;

              Canvas.Font.Color := clBlack;
              Canvas.Brush.Color := TColor(List.Objects[index]);

              DefaultDrawColumnCell(Rect, DataCol, Column, State);
          end;
      end;
end;

Saludos cordiales

Chris 07-01-2011 22:38:59

Cita:

Empezado por Casimiro Notevi (Mensaje 386952)
Creo que no vale, el problema es que almacena en un string los números que ya ha presentado para saber con qué color presentarlo, para ello hay que recorrer desde el principio hasta el final todos los registros. Si por ejemplo vas directamente al último con ctrl+fin entonces no guarda esos valores y no puede pintarlos.

Tienes razón. De hecho, ni conocía -o ya se me había olvidado- ese acceso por teclado (CRTL + END). Habrá que modificar el código entonces. Teniendo en cuenta lo que has dicho, podría almacenarse los número al momento de cambiar el registro actual. No sé exactamente como se haría esto, pero debe haber alguna forma de hacerlo.

Casimiro Notevi 07-01-2011 22:48:58

Cita:

Empezado por rgstuamigo
[..] invalidate [..]

He probado 3 alternativas y con el invalidate y sin él... hace lo mismo :confused:


Cita:

Empezado por Chris (Mensaje 386955)
Tienes razón. De hecho, ni conocía -o ya se me había olvidado- ese acceso por teclado (CRTL + END).

Está duro de roer el hueso :)

Cita:

Empezado por cloayza (Mensaje 386954)
Una pequena optimizacion de codigo que propuse anteriormente.

Nada, acaba alternando colores incorrectamente.


Casimiro Notevi 07-01-2011 22:50:38

Cita:

Empezado por roman (Mensaje 386953)
No sé si sirva para esto, pero lo más parecido que he encontrado en Firebird para las variables de usuario de MySQL es RDB$SET_CONTEXT() y RDB$GET_CONTEXT().

Podrías probar a ver si funcionan similarmente.
// Saludos

Voy a ver qué encuentro sobre eso :)

roman 07-01-2011 22:55:52

Cita:

Empezado por Chris (Mensaje 386955)
Tienes razón. De hecho, ni conocía -o ya se me había olvidado- ese acceso por teclado (CRTL + END). Habrá que modificar el código entonces.

Es que no sólo es eso. Hay muchas formas de desplazarse por un DBGrid. De entrada puedes arrastrar el botón de la barra de desplazamiento a una posición arbitraria, o puedes moverte por código, por ejemplo, mediante una búsqueda, etc.

El evento DrawColumnCell existe porque en la práctica es casi imposible predecir cuales celdas han de dibujarse. Por ello es que considero que cualquier técnica que recurra a una suerte de "último valor" fallará tarde o temprano pues presupone un pintado secuencial de las filas, cosa que no siempre se dará de esa manera.

// Saludos

Casimiro Notevi 08-01-2011 00:33:27

Cita:

Empezado por roman (Mensaje 386819)
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

Cómo se traduce esta línea a:
if (@asiento <> asiento, @colorear:=1-@colorear, @colorear) as colorear, @asiento:=asiento

if @asiento<>asiento then
@colorear = 1-@colorear
else
@asiento = @colorear;
@asiento = asiento;

Supongo que @loquesea quiere decir que es una variable.

Delphius 08-01-2011 00:56:03

Cita:

Empezado por Chris (Mensaje 386915)
No pensaba en contestarte xq era desvirtuar el hilo. Pero has sido demaciado tosco y necesito contestar tus desagradables palabras.

Bien merecido lo tengo, y si... me pasé de las manos. Era mi total intención llamarte la atención.

Cita:

Empezado por Chris (Mensaje 386915)
Creo que lo que a tí te molesta es una opinión contraria a tus ideas.

No tengo problemas en que se me critique mis ideas. No lo que no pienso tolerar en una persona es pretender acabar un buen debate y discusión exponiendo púlblicamente la frase "¡Y punto!" o similar. Al decirlo ya pretendiste dar por acabado todo intento de negociar o de analizar otras perspectivas.

Y voy a seguir insistiendo... punto final no se vale ganar... yo también puedo ser muy infantil :D y bien gallego.

Y si te quiero llamar la atención lo voy a hacer a mi estilo cómico, y de mal humor... ¿A poco te no agrada NewDelphius? Ba... pensé que lo extrañaban por aquí. :D :p

[quote=Chris;386915]
No critique a cada una de las personas que propuso una solución, hay muchas soluciones propuestas si te fijas en todo el hilo. Critiqué, no solo la solución propuesta por Roman y desarrollada por tí, sino todas las que usen de muleta a la base de datos.
[quote]
A veces nos vemos obligados a emplear esas muletas Cris... entiende eso de una vez.
El que se hace UNA VEZ en todo el sistema no es un gran pecado... ¡entendelo! abrí un poco la cabeza.

Si prestaras atención te darás cuenta que inicialmente yo le estaba dando vueltas por el lado cliente. Y luego viendo como se estaba dando el hilo y aprovechando una SUGERENCIA de roman es que me tomé la buena volutad de seguir por ese lado y ver que más hay.

Soy yo y otros usuarios quienes impulsados por traer nuevas visiones, propuestas y alternativas no nos queremos quedar en un sólo lado.

Y disculpa que lo diga pero no por utilizar esas "salidas fáciles" nos hace ser muletas.

Cita:

Empezado por Chris (Mensaje 386915)
Las critico (en el mejor sentido de la palabra) y lo seguiré haciendo.

Actitudes cerradas la podemos tener todos, aunque reconozco que no eres la persona más cerrada... mi padre te lleva mucha ventaja.

Ojalá Cris no te vea por aquí tratando de darle un giro a tus ideas y desafiar tu postura... sería un duro golpe darle un repaso al archivo de tus palabras.

Te aviso que el tiempo es un buen maestro de que nuestras visiones pueden (y van) a cambiar.

Yo soy bastante crítico, pero al menos dejo un espacio a la posibilidad de un arreglo y de ser un poco más abierto o de darle una posibilidad de que me cautive y se defienda. Tu por parte cerraste las puertas ni bien al comienzo de haber dado la propuesta a Casimiro.

Cita:

Empezado por Chris (Mensaje 386915)
Creo que mi critica no fue en mal modo, si te fijas, eres el único que la ha tomado a mal. Te has ahogado en un vaso de agua sinceramente.

Si lo fue. Yo no voy a permitir que un usuario, sea quien sea, nos haya llamado en forma indirecta, y con cierta soberbia, ineficientes.

Lee tu frase por favor:
Cita:

Empezado por Chris
o es muy buena idea que la base de datos funcione de muleta de un programador que no pudo solucionar un problema de la GUI

Caratulas a un desarrollador de rengo, inepto... que no pudo hacer solucionar un problema sencillo de la GUI.
Ese es el mensaje que transmite tus palabras... Deberías saber que significa llamar a alguien de/usar muletas: rengo, mula, tonto. Obstinado, tosco, grosero.

Llamaste de muletas a Casi, Roman, a mi, y a fjcg02 cuando empezamos a darle una nueva posibilidad. Nos tiraste y sentenciaste en la cara con tu punto final.

Eso no lo voy a permitir.

Yo si he sido muleta en la forma de dirigirme hacia tí, pero no en el hilo al probar otras alternativas.

Cita:

Empezado por Chris (Mensaje 386915)
Sabes leer, pero no interpretar. Casimiro hizo lo correcto, vino a pedir ayuda a otros programadores.

Si, ¡y le tiras en la cara de que no pudo resolver un problema y debe recurrir a una muleta porque es rengo!
Eso no es apropiado Cris.
El vino porque tiene un problema, de no tenerlo no hubiera dicho nada. Tu estuviste de más al meter la muleta.

Ojalá no te veas envuelto en una.

Cita:

Empezado por Chris (Mensaje 386915)
Si así lo quieres ver desde tu distorsionada perspectiva.... allá tú. El que se pretende con aires de superioridad eres tú.

Yo no vine con aires de galantería ni superioridad. Estoy seguro de que aquí en ClubDelphi hay personas que saben muchísimo más que yo.
De que se, se... algo se. Muchísimo no... poco... no sabría decirlo. Pero no puedo ni me atrevería de llamar muletas a otro.

Cita:

Empezado por Chris (Mensaje 386915)
No toleras la más mínima critica a tus opiniones o en este caso, a tu manera de solucionar las cosas.

Admito que puedo llegar a ser intolerante en algunas cosas pero en esto no.
Repito que eres tu el que ha sido intolerante: no toleraste la nueva propuesta que se estaba analizando... repito de nuevo: tu sentenciaste... tu dictaste... tu quisiste poner punto final.

A todo eso yo es que le quiero poner punto final.

Cita:

Empezado por Chris (Mensaje 386915)
No programo desde ayer, sé que es KISS. Yo creo que lo único que sabes es que KISS es la abreviación de "Keep it simple stupid", más no sabes lo que eso conlleva. Puedes aprenderlo aquí.

A ver cris, no me vengas pretender enseñarme lo que significa. Senalé el principio KISS para apuntar que a veces es mejor optar por ciertas simplezas sabiendo que hay otros factores que tu no estabas considerando: entre ellos, que Casimiro está presionado para tenerlo para ayer, que no tiene presupuesto para mucho, que el enfoque que tu estabas dando estaba demostrando no ser el más adecuado.

Se te indicó que había una serie de problemas y tu le seguías dando... eres tu el que se ha sido insistente.

No supiste ver que había algo más que se tenía en cuenta... Y la propuesta KISS de por el lado de la base de datos si bien puede que no sea lo más adecuado al menos podría traer algo de equilibrio y permitiría salir de prisas.

Luego, podría destinar tiempo, para una siguiente versión, o mejora al sistema analizarlo con otras perspectivas.

Cita:

Empezado por Chris (Mensaje 386915)
Si no sabías, hay otra regla en el desarrollo de software: NO DES NADA POR SENTADO. Deberías tenerla siempre en cuenta porque es una de la más importantes.

Una de las más importante pero no la más importante.
Si no hay nada que dejar por sentado... entonces creo yo que te deberías comer esas palabras: diste por sentado, sentenciaste de que habrá problemas de perfomance con el SP. ¿Tienes los suficientes elementos como para afirmar con total certeza de que el SP le será muy lento, que sus usuarios se quejarán?

Deja eso a Casi... tu que quedaste sentado, encerrado en la idea del cliente, en verlo por el lado del swich booleano, de compararlo con una variable "anterior".

Pero te viste muy "lerdo" al no captar de que la solución que tu proponías no estaba correcta.

Me alegra de que insistieras en tus ideas, de que buscaras mejorar tu código pero te veníamos diciendo de una u otra forma que hacía falta algo más.

TU diste por sentado algunas cosas...

Cita:

Empezado por Chris (Mensaje 386915)
Creo que en esa frase te estás reflejando tú. Te juro que no me siento aludido.

Error, te reflejaste tú. Ti diste el punto final hace tiempo... te lo voy a hacer recordar. ¿Viste de feo que alguien te lo diga?
A mi no me afecta en lo más mínimo... yo más que nada te lo señalo para que en lo sucesivo sea más cuidadoso cuando pretendas callar a alguien diciéndole "Punto".

Las palabras te van a rebotar, yo no le voy a seguir dando al debate... No tiene sentido discutir más.... Ya te dije lo que te debía decir, pero te digo que pueden venir otros a decirte que ese "Punto" estuvo de más.

Si no te lo dijeron los demás, no quiere decir que se pueda pasar. Yo al menos no lo iba dejar pasar... Porque al tema lo veníamos tratando bien. Si tu lo querías cerrar, consideré bueno hacerte llamar la atención de que el tema todavía estaba abierto.

Te aviso Cris que no es la primera vez que veo en ti la idea de dar esas estocadas finales.... y no es la primera vez tampoco que intentas pasar de "fino" una indirecta como muletas. En ese entonces no me ví en esos hilos... pero a esta no la dejo pasar.

Saludos,
PD: Disculpen que metiera dervirtuadas al hilo.

Delphius 08-01-2011 00:57:52

Cita:

Empezado por Casimiro Notevi (Mensaje 386966)
Cómo se traduce esta línea a:
if (@asiento <> asiento, @colorear:=1-@colorear, @colorear) as colorear, @asiento:=asiento

if @asiento<>asiento then
@colorear = 1-@colorear
else
@asiento = @colorear;
@asiento = asiento;

Supongo que @loquesea quiere decir que es una variable.

Eefectivamente Casimiro. Es la traducción correcta.
Y el @ es para simbolizar y declarar una variable.... al igual que en MS SQL Server.

Delphius 08-01-2011 01:08:23

La idea de tener una Lista, a modo de campo ficticio como el campo "Colorear" o la idea de un campo en el DBGrid y que no se muestre para que almacena un número identificador del color debería funcionar. :confused:

A como veo, es necesario tener una lista o una estructura, o algo por el estilo, que lleve la referencia sobre el color al pintar. No basta con aplicar técnica de comparación con valores anteriores, o siguientes... hay que verlo globalmente: como un conjunto de registros.

Supuestamente, de ese modo en el evento OnDrawColumnCell se podría consultar dicho valor con algo como Lista[DBGrid.RecNo] y si es 0,1,2 o lo que fuese pintar de un color a otro.

En teoría por más que se dezplazara por los registros, al consultar el RecNo (sabiendo que en la lista estarán todos los registros devueltos por la consulta) se debería poder recuperar el valor correcto y pintar de forma inequívoca la fila.

Es fundamental que exista un proceso que se encargue de analizar el conjunto de datos previamente y llenar la lista con los valores adecuados.
Una vez hecho esto recién ya es posible pintar.

Saludos,

cloayza 08-01-2011 01:20:09

Cita:

Empezado por Casimiro Notevi (Mensaje 386957)
Nada, acaba alternando colores incorrectamente.

Amigo he implementado el codigo en ejemplo de Chris, y me anda de maravillas...

Te copio el codigo completo de la unidad.

Código Delphi [-]
unit Unit24;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, IBCustomDataSet, IBDatabase, StdCtrls, ComCtrls, Grids, DBGrids;

type
  TForm24 = class(TForm)
    gr1: TDBGrid;
    DS1: TDataSource;
    dtp1: TDateTimePicker;
    lb1: TLabel;
    btn1: TButton;
    DB1: TIBDatabase;
    TR1: TIBTransaction;
    QR1: TIBDataSet;
    QR1CODIGOAPUNTE: TIntegerField;
    QR1CODIGOEMPRESA: TIntegerField;
    QR1EJERCICIO: TSmallintField;
    QR1NUMEROASIENTO: TIntegerField;
    QR1LINEAASIENTO: TIntegerField;
    QR1FECHAASIENTO: TDateField;
    QR1CODIGOCUENTA: TIBStringField;
    QR1CONCEPTO: TIBStringField;
    QR1DEBE: TFloatField;
    QR1HABER: TFloatField;
    QR1FECHACREACION: TDateField;
    QR1HORACREACION: TTimeField;
    procedure btn1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure gr1DrawColumnCell(Sender: TObject; const Rect: TRect;
      DataCol: Integer; Column: TColumn; State: TGridDrawState);
    procedure dtp1Exit(Sender: TObject);
  private
    { Private declarations }
{    nValorAnt: Integer;
    FColor, BColor: TColor;
    UltimoValor: Variant;
    BoolSwitch: Boolean;
    GrupoImpar: String;
}
  public
    { Public declarations }
    Sombra:Boolean;
    List:TStrings;
  end;

var
  Form24: TForm24;

implementation

{$R *.dfm}

procedure TForm24.btn1Click(Sender: TObject);
begin
  db1.Open;
  tr1.Active:=True;
  qr1.Close;
  qr1.selectsql.text := 'select * from tbapuntes where codigoempresa=2 and ejercicio=2 and codigoestadoapunte=2 '+
                        'and fechaasiento  between :fechadesde and :fechahasta '+
                        'order by codigoempresa, ejercicio, numeroasiento, lineaasiento';
  qr1.Params[0].AsDate := dtp1.Date;
  qr1.Params[1].AsDate := dtp1.Date;

  if Assigned(List) then
     List.Clear;

  // inicializar los datos del control de grupo
  qr1.Open;
  gr1.SetFocus;
end;

procedure TForm24.dtp1Exit(Sender: TObject);
begin

  btn1.SetFocus;
end;

procedure TForm24.FormClose(Sender: TObject; var Action: TCloseAction);
begin
     DB1.Close;
end;

procedure TForm24.gr1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
   index:Integer;
   fColor:TColor;
begin
      if Not Assigned(List) then
         List:=TStringList.Create;

      with TDBGrid(Sender) do
      begin
         if (gdFocused in State) then
         begin
            Canvas.Font.Color := clWhite;
            Canvas.Brush.Color := clHighlight;
         end
         else
         begin
              Index:=List.IndexOf(DataSource.DataSet.FieldByName('NUMEROASIENTO').AsString);
              if Index=-1 then
              begin
                   if Sombra then fColor:=clYellow  else fColor:=clInfoBk;

                   //fColor:=RGB(Random(205),Random(205),Random(205));

                   index:=List.AddObject(Datasource.Dataset.FieldByName('NUMEROASIENTO').AsString, Pointer(fColor));

                   Sombra := not Sombra;
              end;

              Canvas.Font.Color := clBlack;
              Canvas.Brush.Color := TColor(List.Objects[index]);

              DefaultDrawColumnCell(Rect, DataCol, Column, State);
          end;
      end;
end;

end.

Saludos cordiales


La franja horaria es GMT +2. Ahora son las 16:31:20.

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