渐变面板中的闪烁

时间:2011-08-25 19:37:48

标签: delphi gradient tpanel

我从TPanel继承了一个控件,在Paint事件处理程序中,我使用渐变绘制了整个客户端rect。在用户调整大小之前,这完全正常。 调整面板大小时,面板组件会闪烁太多。

我怎样才能避免这种闪烁。我在MS Office 2007中看到了渐变,即使我们调整了客户区域的大小,也不会有闪烁。请赐教我。

感谢您的期待

2 个答案:

答案 0 :(得分:2)

您可能需要查看此问题How to eliminate the flicker on the right edge of TPaintBox (for example when resizing)

很好地概述了避免闪烁的选项以及TPanel。

编辑: 我在Windows 7上的Delphi XE版本中进行了快速测试。

使用此代码,我无法重现任何闪烁。 删除了继承的Paint,并且Paint例程非常快。

如果您仍然可以看到闪烁,可以实现Simon的提议,但最好保留在组件本身的生命周期内创建的位图。

unit MainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TGradientPanel = class(TPanel)
  protected
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    sPanel : TGradientPanel;
  public
    { Public declarations }
 end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

Uses Math;

 procedure GradVertical(Canvas:TCanvas; Rect:TRect; FromColor, ToColor:TColor) ;
 var
   Y:integer;
   dr,dg,db:Extended;
   C1,C2:TColor;
   r1,r2,g1,g2,b1,b2:Byte;
   R,G,B:Byte;
   cnt:Integer;
 begin
    C1 := FromColor;
    R1 := GetRValue(C1) ;
    G1 := GetGValue(C1) ;
    B1 := GetBValue(C1) ;

    C2 := ToColor;
    R2 := GetRValue(C2) ;
    G2 := GetGValue(C2) ;
    B2 := GetBValue(C2) ;

    dr := (R2-R1) / Rect.Bottom-Rect.Top;
    dg := (G2-G1) / Rect.Bottom-Rect.Top;
    db := (B2-B1) / Rect.Bottom-Rect.Top;

    cnt := 0;
    for Y := Rect.Top to Rect.Bottom-1 do
    begin
       R := R1+Ceil(dr*cnt) ;
       G := G1+Ceil(dg*cnt) ;
       B := B1+Ceil(db*cnt) ;

       Canvas.Pen.Color := RGB(R,G,B) ;
       Canvas.MoveTo(Rect.Left,Y) ;
       Canvas.LineTo(Rect.Right,Y) ;
       Inc(cnt) ;
    end;
 end;


constructor TGradientPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Self.ParentBackground := FALSE;
end;

procedure TGradientPanel.Paint;
var
  rect : TRect;
begin
  //inherited;  // Avoid any inherited paint actions as they may clear the panel background
  rect := GetClientRect;
  GradVertical( Self.Canvas, rect, clBlue, clRed);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  sPanel := TGradientPanel.Create( Self);
  sPanel.Parent := Self;
  sPanel.Top := 10;
  sPanel.Left := 10;
  sPanel.Width := 300;
  sPanel.Height := 300;
  sPanel.Anchors := [akLeft,akRight,akTop,akBottom];
  sPanel.Enabled := TRUE;
  sPanel.Visible := TRUE;
end;

end.

答案 1 :(得分:0)

减少闪烁的方法是将渐变绘制到临时位图,将位图的全部内容绘制到面板。此方法假定您在继承的面板中有一个OnPaint方法和一个要绘制的画布。

这样的事情(未经测试)

var bmp : Tbitmap;

procedure AfterConstruction;
begin
  bmp := TBitmap.Create;
end;

procedure Destroy()
begin
  if Assigned(bmp) then FreeandNil(bmp);
end;

//redraw you bmp gradient
procedure Panel1.OnResize();
begin
  if Assigned(bmp) then //ensure the bmp s created in your constructor
  begin
  try
    bmp.SetBounds(Panel1.Clientrect); //ensure the bmp is the same size as the panel
    //draw your gradient on the bmp
    Panel1.OnPaint();//repaint the tpanel

  finally
    bmp.Free;
  end;
end;

//paint to the panel
procedure Panel1.OnPaint()
begin
  Panel1.Canvas.Draw(0,0,bmp); //use the OnPaint method to draw to the canvas
end;
  end;
end;