【问题标题】:Flicker in Gradient panel渐变面板中的闪烁
【发布时间】:2011-11-04 00:03:07
【问题描述】:

我从 TPanel 继承了一个控件,在 Paint 事件处理程序中,我使用渐变绘制了整个客户端矩形。在用户调整大小之前,这工作得很好。 调整面板大小时,面板组件闪烁过多。

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

感谢期待

【问题讨论】:

标签: delphi gradient tpanel


【解决方案1】:

你可能想看看这个问题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.

【讨论】:

  • 这不是答案,应该是对原始问题的评论。 :)
  • @Ken,好的,我在主题中添加了更多内容。
【解决方案2】:

减少闪烁的一种方法是将渐变绘制到临时位图上,将位图的全部内容绘制到面板上。此方法假定您有一个 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;

【讨论】:

  • DoubleBuffered 属性确实可以为您做到这一点吗?
  • 将 ParentBackground 设置为 false 已解决闪烁问题。谢谢你们提供好的意见。
猜你喜欢
  • 2017-09-08
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 1970-01-01
  • 2014-03-19
相关资源
最近更新 更多