我从TPanel继承了一个控件,在Paint事件处理程序中,我使用渐变绘制了整个客户端rect。在用户调整大小之前,这完全正常。 调整面板大小时,面板组件会闪烁太多。
我怎样才能避免这种闪烁。我在MS Office 2007中看到了渐变,即使我们调整了客户区域的大小,也不会有闪烁。请赐教我。
感谢您的期待
答案 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;