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)

José Luis Garcí 05-01-2011 09:25:26

Casimiro, si me permites mi opinión, por que no usasun sistema de control por asientos, asignando al último digito del asiento, en el grid en el envento OnDrawColumCell... (no recuerdo el nombre exacto), como digo según sea este último digito, se rellene la fila de un color, lo cual te permite 10 colores diferentes del grid, ya sería mucha casualidad, dos asientos con la misma terminación para que sea el mismo color, y a unque esto ocurriese, podrias usar una variable local de 0 a 9, y cada vez que cambiaz de valor el asiento, cambias este valor y asignas color a la fila.

Espero se entienda mi idea.

fjcg02 05-01-2011 09:36:52

Cita:

Empezado por Delphius (Mensaje 386664)

Por ejemplo:

1 - Blanco
3 - Rojo
10 - Blanco
11 - Rojo
...

ATHLETIC DE BILBAO 1 - BARCELONA 0

El ATHLETIC a octavos de final en la copa !!

:D:D:D:D:D:D:D:D:D:D

ElKurgan 05-01-2011 09:44:40

Creo que el problema viene que, cuando pintamos la primera columna y preguntamos si el dato cambia, cambiamos el color (correcto); pero no podemos cambiar la variable que controla dicho cambio, porque entonces, el resto de las columnas volverían a cambiar.

He probado con esto y me ha funcionado:

Código Delphi [-]
 
var
  Dato: string = '';
  Color: TColor = clWindow;
...
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if DBgrid1.DataSource.Dataset.FieldbyName('campo').AsString <> Dato then
  begin
    // sólo debe cambiar de color en la primera columna.
    if Column.Index = 0 then
      if Color = clSkyBlue then
        Color := clWindow
      else
        Color := clSkyBlue;
     Dato := 
       DBgrid1.DataSource.Dataset.FieldbyName('campo').AsString   
  end;
  DBGrid1.Canvas.Brush.Color := Color;
  DBGrid1.DefaultDrawDataCell(Rect, Column.Field, State);
end;

Prueba a ver si te vale
Un saludo

Aleca 05-01-2011 10:36:58

le estuve dando un poco de vuelta al asunto y se armas un campo calculado que lleve el color en que se va a pintar (0-blanco, 1-Verde) y pintas de acuerdo al valor de ese campo.
Código Delphi [-]
....
  private
    { Private declarations }
    nValorAnt, nColor: Integer;
    FColor, BColor: TColor;
...
procedure TForm1.DBGDatosDrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if State = [] then
  begin
    if TblArticulosCAMPO_COLOR.AsInteger = 0 then
      begin
        FColor := clWhite;
        BColor := clGreen;
      end
      else
      begin
        FColor := clBlack;
        BColor := clWhite;
      end;
    TDBGrid(Sender).Canvas.Font.Color := FColor;
    TDBGrid(Sender).Canvas.Brush.Color := BColor;
  end
  else
    TDBGrid(Sender).Canvas.Font.Color := clWhite;
  TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
  nValorAnt := 0;
  nColor := 0;
  FColor := clWhite;
  BColor := clGreen;
end;

procedure TForm1.TblArticulosCalcFields(DataSet: TDataSet);
begin
  if nValorAnt <> TblArticulosID_GRUPO.AsInteger then
  begin
    nValorAnt := TblArticulosID_GRUPO.AsInteger;
    if nColor = 0 then
      nColor := 1
    else
      nColor := 0;
  end;
  TblArticulosCAMPO_COLOR.AsInteger := nColor;
end;
end.

ahora me lo mantiene estable.
Saludos :)

Aleca 05-01-2011 10:42:53

Cita:

Empezado por Aleca (Mensaje 386673)
le estuve dando un poco de vuelta al asunto y se armas un campo calculado que lleve el color en que se va a pintar (0-blanco, 1-Verde) y pintas de acuerdo al valor de ese campo.

ahora me lo mantiene estable.Saludos :)

umm lo segui revisando y en algun momento lo cambia:mad:

ElKurgan 05-01-2011 10:53:28

Cita:

Empezado por ElKurgan (Mensaje 386672)
Código Delphi [-]
 
  Color: TColor = clWindow;

Mejor cambiar el nombre de la variable, porque a veces puede confundirse con la propiedad Color del Formulario; en algunas ocasiones me la ha interpretado como "Self.Color"

Saludos

fjcg02 05-01-2011 11:56:56

Cita:

Empezado por Aleca (Mensaje 386673)
le estuve dando un poco de vuelta al asunto y se armas un campo calculado que lleve el color en que se va a pintar (0-blanco, 1-Verde) y pintas de acuerdo al valor de ese campo.

Estoy de acuerdo en que si no vale ninguna de las soluciones dadas, la siguiente es en lugar de utilizar una query utilizar un procedimiento almacenado que devuelva una columna adicional, que sea el color a pintar.

Saludos
PD: Cuando Casi vea el revuelo que ha formado igual le da un patatús.

Casimiro Notevi 05-01-2011 13:22:48

jajaja... bueeenooo... ¡¡¡ vaya jaleo !!! :D
Muchísimas gracias a todos :)

Y sí, me piden que esté ordenado por fecha y luego por asiento/apunte, pero como cada asiento son varios apuntes...
No sé, el tema no parece muy complicado, al contrario, pero sin embargo se está complicando.

El asunto es que cada asiento son varios registros (apuntes) y cuando hay un número impar de asientos (y en otros casos que no he detectado el motivo) al terminar de pintar el último se queda con el color igual al primer registro, entonces al posicionarse en el primero e intentar mover el cursor a otro... lo pinta del color que no le corresponde.

Se hace el select y pinta el dbgrid:
asiento 1 apunte 1 azul
asiento 1 apunte 2 azul
asiento 1 apunte 3 azul
asiento 2 apunte 1 rojo
asiento 2 apunte 2 rojo

asiento 3 apunte 1 azul
asiento 3 apunte 2 azul
<-- en memoria queda último color usado: azul

Entonces se posiciona en el primer registro, y si muevo el cursor al siguiente, por ejemplo, al estar en azul... lo pinta e rojo. Alterna los colores.

Cuando el número de asientos es par entonces no hay problema
asiento 1 apunte 1 azul
asiento 1 apunte 2 azul
asiento 1 apunte 3 azul
asiento 2 apunte 1 rojo
asiento 2 apunte 2 rojo

asiento 3 apunte 1 azul
asiento 3 apunte 2 azul

asiento 4 apunte 1 rojo
asiento 4 apunte 2 rojo
<-- en memoria queda último color usado: rojo

Al posicionarse en el primero y movernos, cambia rojo por azul, que es el color correcto.



En fin, que voy a hacerlo de otra forma, ya habéis dado pistas sobre eso, un campo calculado que vaya anotando cada vez que cambia de asiento y listo, luego se pinta del color según ese campo, (true/false ó 0/1).
O cargarlo en un clientdataset o tabla en memoria y hacer lo mismo.

Y de nuevo muchísimas gracias a todos :)
Si se os ocurre una forma "normal" y que funcione... avisáis :)

ElKurgan 05-01-2011 14:19:14

Pues no se, a mi me funciona lo que he probado. Creía que bastaría con adaptarlo un poco a tu programa y ya está

En fin, mi gozo en un pozo

Saludos

Casimiro Notevi 05-01-2011 14:21:59

Cita:

Empezado por ElKurgan (Mensaje 386685)
Pues no se, a mi me funciona lo que he probado. Creía que bastaría con adaptarlo un poco a tu programa y ya está
En fin, mi gozo en un pozo
Saludos

Espera, que todavía no lo he probado todo, déjame un poquito de tiempo :)

ecfisa 05-01-2011 16:11:04

Hola.

Dudo de su aplicabilidad... pero brinda un 'arco iris' de posibilidades... :)
Código Delphi [-]
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  Num,Base: Integer;
begin
  Num:= DBGrid1.DataSource.DataSet.FieldByName('ASIENTO').AsInteger;
  if Odd(Num) then
    Base:=  Integer(clRed)
  else
    Base:=  Integer(clBlue);
  DBGrid1.Canvas.Font.Color:= clWhite;
  DBGrid1.Canvas.Brush.Color:= TColor(Base + Num * 100);
  DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;

Saludos.

duilioisola 05-01-2011 17:22:59

Creo que la solución sería:
  • Poner AutoCalcFields = False;
  • Crear un campo calculado que contenga el color con el que debe pintarse
  • Cuando se abra la tabla, se deberá hacer un FetchAll y dejar que el OnCalcFields calcule el varlor del color.
Código Delphi [-]
var
   ValorAnterior: string;
   Sombra : boolean;

procedure TDataModule.TablaBeforeOpen(DataSet: TDataSet);
begin
   Sombra := False;
   ValorAnterior := '';
end;

procedure TDataModule.TablaOnCalcFields(DataSet: TDataSet);
begin
   if (ValorAnterior<>TablaNRO_ASIENTO.AsString) then
      Sombra := not Sombra;
   TablaCAMPO_CALCULADO_SOMBRA.AsBoolean := Sombra;
end;

Nota: Según la ayuda de Delphi 6:

Cita:

When AutoCalcFields is True (the default), Lookup fields are recalculated and OnCalcFields is triggered when:

The dataset is opened.
The dataset is put into dsEdit state.
Focus moves from one visual control to another, or from one column to another in a data-aware grid and modifications have been made to the record.

When AutoCalcFields is False, Lookup fields are recalculated and the OnCalcFields event occurs only when

The dataset is opened.
The dataset is put into dsEdit state.
A record is retrieved from a database.

pacopenin 05-01-2011 17:27:07

Cita:

Empezado por duilioisola (Mensaje 386700)
Creo que la solución sería:
  • Poner AutoCalcFields = False;
  • Crear un campo calculado que contenga el color con el que debe pintarse
  • Cuando se abra la tabla, se deberá hacer un FetchAll y dejar que el OnCalcFields calcule el varlor del color.
Código Delphi [-]
var    ValorAnterior: string;    
Sombra : boolean;  
procedure TDataModule.TablaBeforeOpen(DataSet: TDataSet); 
begin    
  Sombra := False;    
  ValorAnterior := ''; 
end;  
procedure TDataModule.TablaOnCalcFields(DataSet: TDataSet); 
begin    
 if (ValorAnterior<>TablaNRO_ASIENTO.AsString) then       
  Sombra := not Sombra;    
 TablaCAMPO_CALCULADO_SOMBRA.AsBoolean := Sombra; 
end;

Yo creo que los tiros van por ahí. Solo si tenemos en la tabla un valor que nos defina el color podremos "dibujar" el grid y desplazarnos (saltando) entre registros.

duilioisola 05-01-2011 18:29:49

Al final he hecho lo siguiente:

Código Delphi [-]
{En el Form}
procedure TFCMayor.DBGConsultaDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: integer; Column: TColumn; State: TGridDrawState);
begin
  with TDBGrid(Sender) do
  begin
     if (gdFocused in State) then //If the cell has the focus
     begin
        Canvas.Font.Color := clWhite;
        Canvas.Brush.Color := clHighlight;
     end
     else
        if (DMMayor.xMayorSOMBRA.AsInteger = 1) then
        begin
           Canvas.Font.Color := clBlack;
           Canvas.Brush.Color := clCream;
        end
        else
        begin
           Canvas.Font.Color := clBlack;
           Canvas.Brush.Color := clInfoBk;
        end;
     DefaultDrawColumnCell(Rect, DataCol, Column, State);
  end;
end;

{En el DataModule}
{Pongo xMayor.AutoCalcFields en False}
{Campo calculado xMayorSOMBRA integer}

var
   Sombra : boolean;
   ValorAnterior : string;

procedure TDMMayor.xMayorBeforeOpen(DataSet: TDataSet);
begin
   Sombra := False;
   ValorAnterior := '';
end;

procedure TDMMayor.xMayorCalcFields(DataSet: TDataSet);
begin
   if (ValorAnterior<>xMayorASIENTO.AsString) then
   begin
      Sombra := not Sombra;
      ValorAnterior := xMayorASIENTO.AsString;
   end;
   if (Sombra) then
      xMayorSOMBRA.Value := 1  {<-- Esta asignacion no funciona}
   else
      xMayorSOMBRA.Value := 0; {<-- Esta asignacion no funciona}
end;

El único problema es que la última parte donde asigno al campo sombra un valor, la pasa por alto y siempre es 0.

He probado con AutoCalcFields en False y en True, con el mismo resultado.

Puede ser porque estoy probando con unos componentes que descienden de FreeIB.

Si alguien lo puede probar con otros componentes DataSets que informe si le funciona.

José Luis Garcí 05-01-2011 18:42:16

Casimiro te pongo unas imágenes de lo que te comentaba anteriormente













Ten en cuenta que usado colores a lo loco, deberías usar, un color y derivar luego de este cambiado sólo uno de los valores de la rgb para que fueran tonalidades mas consecutivas.


La parte del código que creo te puede interesar es esta

Código Delphi [-]

function UlDigit(nNumero: integer): Integer;
var
udTama,udResult:Integer;
cNumero:string;
begin
   cNumero:=IntToStr(nNumero);
   udTama:=Length(cNumero);
   if udTama>1 then udResult:=StrToInt(Copy(cNumero,((udTama)),1))
               else udResult:=StrToInt(cNumero);
   Result := udResult;
end;

procedure TForm1.DBGrid2DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var color:TColor;
begin
     case UlDigit(StrToInt(DataSource2.DataSet.FieldByName('LOTE').value)) of
        0:Color:=ColorBox10.Selected;
        1:Color:=ColorBox12.Selected;
        2:Color:=ColorBox13.Selected;
        3:Color:=ColorBox14.Selected;
        4:Color:=ColorBox15.Selected;
        5:Color:=ColorBox16.Selected;
        6:Color:=ColorBox17.Selected;
        7:Color:=ColorBox18.Selected;
        8:Color:=ColorBox19.Selected;
        9:Color:=ColorBox20.Selected;
     end;
     DBGrid2.Canvas.Brush.Color := Color;
     Dbgrid2.Canvas.FillRect(Rect);
     dbGrid2.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;


Como puedes comprobar use mi BD de pruebas y el Campo por el que hago la comprobación es LOTE, en tu caso sería ASIENTO

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

Bueno siento ser pesado, pero con unos pequeños cambios os muestro lo que digo.







Código Cambiado

Código Delphi [-]
procedure TForm1.DBGrid2DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var color:TColor;
begin
//     if odd then
     case UlDigit(StrToInt(DataSource2.DataSet.FieldByName('LOTE').value)) of
        0:Color:=RGB(205,150,10);
        1:Color:=RGB(210,160,40);
        2:Color:=RGB(215,170,70);
        3:Color:=RGB(220,180,100);
        4:Color:=RGB(225,190,130);
        5:Color:=RGB(230,200,160);
        6:Color:=RGB(235,210,190);
        7:Color:=RGB(240,220,210);
        8:Color:=RGB(245,230,240);
        9:Color:=RGB(250,240,255);
//        0:Color:=ColorBox10.Selected;
//        1:Color:=ColorBox12.Selected;
//        2:Color:=ColorBox13.Selected;
//        3:Color:=ColorBox14.Selected;
//        4:Color:=ColorBox15.Selected;
//        5:Color:=ColorBox16.Selected;
//        6:Color:=ColorBox17.Selected;
//        7:Color:=ColorBox18.Selected;
//        8:Color:=ColorBox19.Selected;
//        9:Color:=ColorBox20.Selected;
     end;
     DBGrid2.Canvas.Brush.Color := Color;
     Dbgrid2.Canvas.FillRect(Rect);
     dbGrid2.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;

Chris 05-01-2011 19:36:24

mmm... comparto la opinión de casimiro, las soluciones presentadas son como cañonazos.

Por mi parte creo que este problema necesita nada más que una especie de switch, o alternador. Una simple variable booleana que controle el color utilizado.

Código Delphi [-]
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
    background_colors: array[0..1] of TColor = (clBtnFace, clWhite);
begin
if Dataset.FieldByName('asiento').Value <> UltimoValor then
    BoolSwitch := (not BoolSwitch);

TDBGrid(Sender).Canvas.Brush.Color := background_colors[BoolSwitch];
TDBGrid(Sender).DefaultDrawColumnCell( ... );
UltimoValor := Dataset.FieldByName('asiento').Value;
...
end;

BoolSwitch y UltimoValor son variables privadas del formulario.

Creo que con este código se pudiera solucionar el problema. Sino pues creo que de él se puede partir.

Saludos,
Chris

pacopenin 05-01-2011 19:46:01

Estoy siguiendo este hilo con interés. En algún momento voy a verme en la tesitura de implantar algo similar. Y creo que el principal problema no es "pintar" las filas cuando se "cargan" los datos. Eso, con los sistemas de switch que se van comentando es fácil. Yo creo que el principal problema es la navegación, el hacer click en cualquier sitio. Creo que si en el registro de la tabla no hay una información que nos indique si hay que pintar esa celda de un color o de otro, los valores del "switch" no van a ser válidos. Mi opinión en que "debe haber una información en el registro que indique de color hay que pintar esa celda".

Saludos,

Casimiro Notevi 05-01-2011 19:51:21

Cita:

Empezado por pacopenin (Mensaje 386720)
[..] Mi opinión en que "debe haber una información en el registro que indique de color hay que pintar esa celda".
Saludos,

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í.

Pero todavía se aceptan más propuestas... habrá premio al que obtenga el resultado correcto :)

Delphius 05-01-2011 20:46:07

Pues yo no veo otra salida amigo. Ya sea que se lleve una estructura fuera o en el mismo dbgrid con un campo calculado y el uso de técnicas "flags booleanas" es necesario contar con un artilugio para llevar ese conteo y poder determinar con que color pintar cada registro.

Saludos,


La franja horaria es GMT +2. Ahora son las 23:36:23.

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