Lazarus
Programming => Widgetset => QT => Topic started by: zamtmn on June 28, 2014, 11:50:12 am
-
I need draw on TPanel outside paintevent.
In gtk2 and win this work:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF LCLQT}
qtwidgets,qt4,
{$ENDIF}
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Panel1: TPanel;
procedure _onCreate(Sender: TObject);
procedure _onMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1._onMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
);
begin
panel1.Canvas.Line(0,0,x,y);
end;
procedure TForm1._onCreate(Sender: TObject);
begin
{$IFDEF LCLQT}
TQtWidget(Panel1.Handle).setAttribute(QtWA_PaintOutsidePaintEvent);
{$ENDIF}
end;
end.
but on qt this not work, although setAttribute(QtWA_PaintOutsidePaintEvent)
Is it possible to achieve such drawing in LCL with qt widgeset?
-
1.That can work only on linux. Mac and win32 won't work according to the qt documentation.
2.LCL-Qt waits for QPaintEvent from qt and then creates context and everything, so I'm not sure that panel1.Canvas.Line(0,0,x,y); can work just like that.
You shuold check if panel1.Canvas.HandleAllocated and if not then
use LCLIntf.BeginPaint() and LCLIntf.EndPaint() to create context and everything.Maybe then it'll work.
-
You don't really need to paint outside paint event. This kind of logic could be easily coded in a way that drawing routine would be called from OnPaint handler. Draw your lines in OnPaint handler and call Invalidate method to make control repaint itself & call your drawing routine. You can use a Timer for this and call Invalidate from OnTimer handler
-
zeljko
>>use LCLIntf.BeginPaint() and LCLIntf.EndPaint() to create context and everything.Maybe then it'll work.
not work((
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF LCLQT}
qtwidgets,qt4,
{$ENDIF}
LCLIntf,LCLType,Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Panel1: TPanel;
procedure _onCreate(Sender: TObject);
procedure _onMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1._onMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
);
var
PaintStruct: TPaintStruct;
begin
LCLIntf.BeginPaint(panel1.Handle,PaintStruct);
panel1.Canvas.Line(0,0,x,y);
LCLIntf.EndPaint(panel1.Handle,PaintStruct);
end;
procedure TForm1._onCreate(Sender: TObject);
begin
{$IFDEF LCLQT}
TQtWidget(Panel1.Handle).setAttribute(QtWA_PaintOutsidePaintEvent);
{$ENDIF}
end;
end.
hinst
No it is only right decision. Invalidate, and especially the timer - will antsy and torn. I need repainting while moving the mouse and not when it stops. Any missed frames worsen behavior
-
zeljko
>>use LCLIntf.BeginPaint() and LCLIntf.EndPaint() to create context and everything.Maybe then it'll work.
not work((
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF LCLQT}
qtwidgets,qt4,
{$ENDIF}
LCLIntf,LCLType,Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Panel1: TPanel;
procedure _onCreate(Sender: TObject);
procedure _onMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1._onMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
);
var
PaintStruct: TPaintStruct;
begin
LCLIntf.BeginPaint(panel1.Handle,PaintStruct);
panel1.Canvas.Line(0,0,x,y);
LCLIntf.EndPaint(panel1.Handle,PaintStruct);
end;
procedure TForm1._onCreate(Sender: TObject);
begin
{$IFDEF LCLQT}
TQtWidget(Panel1.Handle).setAttribute(QtWA_PaintOutsidePaintEvent);
{$ENDIF}
end;
end.
You're doing it wrong.
LCLIntf.BeginPaint(panel1.Handle,PaintStruct);
panel1.Canvas.Line(0,0,x,y);
LCLIntf.EndPaint(panel1.Handle,PaintStruct);
Where do you set PaintStruct values ?
See qtwinapi.inc -> BeginPaint() & EndPaint() what is needed to get it work.Also, your panel1.Canvas.Handle should be assigned from LCLIntf.BeginPaint hdc.
1. TQtWidget(Panel1.Handle).PaintData should be filled properly before calling to BeginPaint()
2.Panel1.Canvas.Handle := LCLIntf.BeginPaint().
3.Maybe I can simplify BeginPaint and automatically fill PaintData in this case, but need test project, for now it must be filled like it is in TQtWidget.SlotPaint().
-
zeljko
Please give an example of filling needed struct based on this:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
{$IFDEF LCLQT}
qtwidgets,qt4,
{$ENDIF}
LCLIntf,LCLType,Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Panel1: TPanel;
procedure _onCreate(Sender: TObject);
procedure _onMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1._onMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
);
var
PaintStruct: TPaintStruct;
begin
LCLIntf.BeginPaint(panel1.Handle,PaintStruct);
panel1.Canvas.Line(0,0,x,y);
LCLIntf.EndPaint(panel1.Handle,PaintStruct);
end;
procedure TForm1._onCreate(Sender: TObject);
begin
{$IFDEF LCLQT}
TQtWidget(Panel1.Handle).setAttribute(QtWA_PaintOutsidePaintEvent);
{$ENDIF}
end;
end.
I can not get it done.