-
Content Count
321 -
Joined
-
Last visited
-
Days Won
3
Everything posted by shineworld
-
Missing attachment from past post. delphivcl_ext.zip
-
Everything described by pyscripter is pure truth. I came to Python because of the need to use OpenCV with Delphi in analyzing frames from camera. There are a couple of wrapper libraries for OpenCV, but when I tried them they were more pains than joys. I then learned about DelphiVCL for python and that fixed the damaging issue of a good UI in Python. The whole phase of capturing frames from IP camera via Python was a bloodbath, too slow and blocking, even using in threads that are not parallel anyway. But Python4Delphi gave me the ability to "move" the heavy, parallel processing into Delphi threads. So I moved the camera communication and frame retrieval into a Delphi class using threads and Indy then exported to Python with P4D, quietly getting the required 30fps. I was then free to use the full power of OpenCV + Skia 4 Python + DelphiVCL + Cython to get a really high performance image processing framework. Yes python can be fast if you roll with it. Obviously doing everything native in Delphi would be another thing...but it is known that importing libraries written in C++ is still impossible, except in rare cases where someone creates a wrapper in C with undoubted complexity of use.
-
You can greatly improve the speed of a python script by passing it through Cython and obtaining compiled pyd (windows dll) or .so (linux library) output modules that can then be imported without any modification into the original code. I use Cython a lot. At the end of a project, through a script, I "cython" all the .py modules to get a version more performant and difficult to reverse engineer. In the middle Cython convert .py to .c and compile to pyd using MSCV or any other C++ compiler.
-
Hi all. Recently I've been using VTK to manage 3D Views. Unfortunately, I've found only info on how to use it with QT Pyside6 with QVTKRenderWindowInteractor. I will hope to use DelphiVCL (my first choice) or DelphiFMX + VTK. Do you have any idea on how to use VTK in a TForm or any other Windows-based window object?
-
OK, I can understand the reasons for this. In my suite I will deploy a custom delphivcl renamed with a different name to avoid any collision with the native version of Embarcadero and installed in python as an offline whl package. The important thing for me was the ability to REMOVE the use of QT and be able to use the VTK 3D management package. At 90% I only program with Delphi, and Python + DelphiVCL + VTK is only for me to create support and research programs. At the end of it all I posted my solution so if anyone else finds themselves in need of using DelphiVCL + VTK they have a starting point for doing so.
-
To fully integrate VTK I had to modify the DelphiVCL sources of Python4Delphi by adding a new VTKPanel class inherited from TCustomControl that exposes OnMouseDown, OnMouseMove, OnMouseUp, OnMouseWheel, OnResize, and OnPaint: {*** * TAKE CARE * ========= * This units add extra components to integrate VTK. * **} {$I ..\Definition.Inc} unit WrapExtVTK; interface uses System.Classes, System.TypInfo, System.SysUtils, Winapi.Windows, Vcl.Controls, Vcl.Graphics, Vcl.StdCtrls, WrapDelphi, PythonEngine, WrapVclControls, WrapDelphiClasses; type TVTKPanel = class(TCustomControl) private FOnPaint: TNotifyEvent; protected procedure Paint; override; published property OnPaint: TNotifyEvent read FOnPaint write FOnPaint; published property OnMouseDown; // TMouseEvent property OnMouseMove; // TMouseMoveEvent property OnMouseUp; // TMouseEvent property OnMouseWheel; // TMouseWheelEvent property OnResize; // TNotifyEvent end; TPyDelphiVTKPanel = class (TPyDelphiControl) private function GetDelphiObject: TCustomControl; procedure SetDelphiObject(const Value: TCustomControl); protected public class function DelphiObjectClass : TClass; override; // Properties property DelphiObject: TCustomControl read GetDelphiObject write SetDelphiObject; end; implementation { TVTKPanel } procedure TVTKPanel.Paint; begin inherited; if Assigned(FOnPaint) then FOnPaint(Self); end; { TPyDelphiVTKPanel } class function TPyDelphiVTKPanel.DelphiObjectClass: TClass; begin Result := TVTKPanel; end; function TPyDelphiVTKPanel.GetDelphiObject: TCustomControl; begin Result := TVTKPanel(inherited DelphiObject); end; procedure TPyDelphiVTKPanel.SetDelphiObject(const Value: TCustomControl); begin inherited DelphiObject := Value; end; { register the wrappers, the globals and the constants } type TThirdPartiesCtrlsRegistration = class(TRegisteredUnit) public function Name : string; override; procedure RegisterWrappers(APyDelphiWrapper : TPyDelphiWrapper); override; procedure DefineFunctions(APyDelphiWrapper : TPyDelphiWrapper); override; procedure DefineVars(APyDelphiWrapper : TPyDelphiWrapper); override; end; { TThirdPartiesCtrlsRegistration } procedure TThirdPartiesCtrlsRegistration.DefineFunctions(APyDelphiWrapper: TPyDelphiWrapper); begin inherited; end; procedure TThirdPartiesCtrlsRegistration.DefineVars(APyDelphiWrapper: TPyDelphiWrapper); begin inherited; end; function TThirdPartiesCtrlsRegistration.Name: string; begin Result := 'ThirdPartiesVTK'; end; procedure TThirdPartiesCtrlsRegistration.RegisterWrappers(APyDelphiWrapper: TPyDelphiWrapper); begin inherited; APyDelphiWrapper.RegisterDelphiWrapper(TPyDelphiVTKPanel); end; initialization RegisteredUnits.Add(TThirdPartiesCtrlsRegistration.Create); System.Classes.RegisterClasses([TVTKPanel]); end. At this point now mouse management and window resizing works well, although during Resize there is a small instant where you see the white container window. from DelphiVCL import * from vtkmodules.vtkRenderingCore import vtkRenderWindow from vtkmodules.vtkRenderingUI import vtkGenericRenderWindowInteractor class vclVTKRenderWindowInteractor(VTKPanel): """ A vclVTKRenderWindowInteractor for Python and DelphiVCL. Uses a vtkGenericRenderWindowInteractor to handle the interactions. Use GetRenderWindow() to get the vtkRenderWindow. """ def __init__(self, owner): super().__init__(self, owner) # set default member values self._render_window = None self._render_interactor = None self._render_interactor_timer = None # assign control events self.OnMouseDown = self._on_mouse_down self.OnMouseMove = self._on_mouse_move self.OnMouseWheel = self._on_mouse_wheel self.OnMouseUp = self._on_mouse_up self.OnPaint = self._on_paint self.OnResize = self._on_resize def __getattr__(self, attr): """Makes the object behave like a vtkGenericRenderWindowInteractor""" if attr == '__vtk__': return lambda t=self._render_interactor: t elif hasattr(self._render_interactor, attr): return getattr(self._render_interactor, attr) else: raise AttributeError(self.__class__.__name__ + " has no attribute named " + attr) def _on_mouse_down(self, Sender, Button, Shift, X, Y): ctrl = 'ssCtrl' in Shift shift = 'ssShift' in Shift self._render_interactor.SetEventInformationFlipY(X, Y, ctrl, shift) if Button == 0: self._render_interactor.InvokeEvent("LeftButtonPressEvent") elif Button == 1: self._render_interactor.InvokeEvent("RightButtonPressEvent") elif Button == 2: self._render_interactor.InvokeEvent("MiddleButtonPressEvent") def _on_mouse_move(self, Sender, Shift, X, Y): ctrl = 'ssCtrl' in Shift shift = 'ssShift' in Shift self._render_interactor.SetEventInformationFlipY(X, Y, ctrl, shift, chr(0), 0, None) self._render_interactor.MouseMoveEvent() def _on_mouse_up(self, Sender, Button, Shift, X, Y): ctrl = 'ssCtrl' in Shift shift = 'ssShift' in Shift self._render_interactor.SetEventInformationFlipY(X, Y, ctrl, shift) if Button == 0: self._render_interactor.InvokeEvent("LeftButtonReleaseEvent") elif Button == 1: self._render_interactor.InvokeEvent("RightButtonReleaseEvent") elif Button == 2: self._render_interactor.InvokeEvent("MiddleButtonReleaseEvent") def _on_mouse_wheel(self, Sender, Shift, WheelDelta, MousePos, Handled): x = MousePos.X y = MousePos.Y ctrl = 'ssCtrl' in Shift shift = 'ssShift' in Shift self._render_interactor.SetEventInformationFlipY(x, y, ctrl, shift, chr(0), 0, None) if WheelDelta > 0: self._render_interactor.MouseWheelForwardEvent() else: self._render_interactor.MouseWheelBackwardEvent() Handled.Value = True def _on_resize(self, Sender): width = Sender.ClientWidth height = Sender.ClientHeight if self._render_window: self._render_window.SetSize(width, height) self._render_interactor.ConfigureEvent() self.Repaint() def _on_paint(self, Sender): pass if not self._render_interactor is None: self._render_interactor.Render() # == BEG: xxx # def GetRenderWindow(self): if self._render_window is None: # create render window and assign handle of this component hwnd = self.Handle self._render_window = vtkRenderWindow() self._render_window.SetWindowInfo(str(int(hwnd))) # create render interactor as generic render window interactor self._render_interactor = vtkGenericRenderWindowInteractor() self._render_interactor.SetRenderWindow(self._render_window) # add render interactor timer events to the observer self._render_interactor.AddObserver('CreateTimerEvent', self.CreateTimer) self._render_interactor.AddObserver('DestroyTimerEvent', self.DestroyTimer) return self._render_window def Render(self): self.update() def CreateTimer(self, obj, evt): if self._render_interactor_timer is None: self._render_interactor_timer = Timer(self) self._render_interactor_timer.Enabled = False self._render_interactor_timer.Interval = 10 self._render_interactor_timer.OnTimer = self.TimerEvent self._render_interactor_timer.Enabled = True def DestroyTimer(self, obj, evt): self._render_interactor_timer.Enabled = False return 1 def TimerEvent(self, Sender): if not self._render_interactor is None: self._render_interactor.TimerEvent() # # == END: xxx def vclVTKRenderWindowInteractorConeExample(): """A simple example that uses the vclVTKRenderWindowInteractor class.""" from vtkmodules.vtkFiltersSources import vtkConeSource from vtkmodules.vtkRenderingCore import vtkActor, vtkPolyDataMapper, vtkRenderer import vtkmodules.vtkRenderingOpenGL2 import vtkmodules.vtkInteractionStyle class MainView(Form): def __init__(self, owner): super().__init__(owner) self.vtk_panel = vclVTKRenderWindowInteractor(self) self.vtk_panel.Parent = self self.vtk_panel.Align = 'alClient' self.vtk_panel.AlignWithMargins = True # set default control values self.DoubleBuffered = True # set main form events handlers self.OnClose = self.__on_form_close def __on_form_close(self, sender, action): if sender is None: return if sender == self: action.Value = caFree # initialize application Application.Initialize() Application.Title = "" # create and show view view = MainView(Application) try: def on_timer(Sender): coneActor.RotateX(5) coneActor.RotateY(2.5) coneActor.RotateY(1) widget.GetRenderWindow().Render() timer.interval = 100 view.Show() widget = view.vtk_panel ren = vtkRenderer() widget.GetRenderWindow().AddRenderer(ren) cone = vtkConeSource() cone.SetResolution(8) coneMapper = vtkPolyDataMapper() coneMapper.SetInputConnection(cone.GetOutputPort()) coneActor = vtkActor() coneActor.SetMapper(coneMapper) ren.AddActor(coneActor) # initialize and start render interactor widget.Initialize() widget.Start() timer = Timer(None) timer.Interval = 1000 timer.OnTimer = on_timer FreeConsole() Application.Run() finally: view.Destroy() if __name__ == '__main__': vclVTKRenderWindowInteractorConeExample() Final result: Unfortunately VTKPanel will be available only with a custom DelphiVCL Python. Will be interesting to have a native control which does same behaviour aka ExternControl or similar name to manage Python objects can work with a windowed delphivcl control using window handle.
-
Do not miss to add OnClose event in the main form and evaluate action for caFree class DesktopView(Form): def __init__(self, owner): # call vcl inherited view constructor super().__init__(owner) ... # set main form events handlers self.OnClose = self.__on_form_close ... def __on_form_close(self, sender, action): if sender is None: return if sender == self: action.Value = caFree ... def main(): # initialize application Application.Initialize() Application.Title = "" # create and show main_view main_view = DesktopView(Application) try: main_view.Show() FreeConsole() Application.Run() finally: main_view.Destroy() # main entry point if __name__ == "__main__": main()
-
A few small steps forward... Now VTK is displaying quite well but putrously I still haven't quite figured out if CustomControl is the right "hook" point for VTK. VTK requires docking to a control with Handle. But I assume Paint's native handling of the control should come disabled. Also, CustomControl (TCustomControl) lacks OnMouseXXX events to capture events to send to VTK's iterator. Perhaps the only solution is to add a control derived from TWindowControl to DelphiVCL that would accommodate what VTK requires for integration. In the video the comparison of the same code in DelphiVCL and PySide6 (QT), which I want to get rid of as soon as possible.
-
The code is a real crap, I'm just trying the right way to get the thing working, but Python + DelphiVCL + VTK looks like it could go. from delphivcl import * from vtkmodules.vtkRenderingCore import vtkRenderWindow from vtkmodules.vtkRenderingUI import vtkGenericRenderWindowInteractor BASE_CLASS_NAME = WinControl class vclVTKRenderWindowInteractor(BASE_CLASS_NAME): def __init__(self, owner): BASE_CLASS_NAME.__init__(self, owner) self._RenderWindow = None self._Iren = None def __getattr__(self, attr): """Makes the object behave like a vtkGenericRenderWindowInteractor""" if attr == '__vtk__': return lambda t=self._Iren: t elif hasattr(self._Iren, attr): return getattr(self._Iren, attr) else: raise AttributeError(self.__class__.__name__ + " has no attribute named " + attr) def GetRenderWindow(self): if self._RenderWindow is None: hwnd = self.Handle self._RenderWindow = vtkRenderWindow() self._RenderWindow.SetWindowInfo(str(int(hwnd))) self._Iren = vtkGenericRenderWindowInteractor() self._Iren.SetRenderWindow(self._RenderWindow) return self._RenderWindow def Render(self): self.update() def vclVTKRenderWindowInteractorConeExample(): """A simple example that uses the vclVTKRenderWindowInteractor class.""" from vtkmodules.vtkFiltersSources import vtkConeSource from vtkmodules.vtkRenderingCore import vtkActor, vtkPolyDataMapper, vtkRenderer import vtkmodules.vtkRenderingOpenGL2 import vtkmodules.vtkInteractionStyle class MainView(Form): def __init__(self, owner): self.vtk_panel = vclVTKRenderWindowInteractor(self) self.vtk_panel.Parent = self self.vtk_panel.Align = 'alClient' self.vtk_panel.AlignWithMargins = True self.vtk_panel.BevelInner = 'bvNone' self.vtk_panel.BevelKind = 'bkFlat' self.vtk_panel.BevelOuter = 'bvNone' self.vtk_panel.Color = clCream self.vtk_panel.ParentBackground = False self.vtk_panel.Caption = 'Hello World!' # set main form events handlers self.OnClose = self.__on_form_close def __on_form_close(self, sender, action): if sender is None: return if sender == self: action.Value = caFree # initialize application Application.Initialize() Application.Title = "" # create and show view view = MainView(Application) try: def on_timer(Sender): coneActor.RotateX(10) coneActor.RotateY(5) coneActor.RotateY(2.5) widget.GetRenderWindow().Render() timer.interval = 100 view.Show() widget = view.vtk_panel ren = vtkRenderer() widget.GetRenderWindow().AddRenderer(ren) cone = vtkConeSource() cone.SetResolution(8) coneMapper = vtkPolyDataMapper() coneMapper.SetInputConnection(cone.GetOutputPort()) coneActor = vtkActor() coneActor.SetMapper(coneMapper) ren.AddActor(coneActor) widget._Iren.Initialize() # Initialize the interactor widget._Iren.Start() # Start the interactor timer = Timer(None) timer.Interval = 1000 timer.OnTimer = on_timer FreeConsole() Application.Run() finally: view.Destroy() if __name__ == '__main__': vclVTKRenderWindowInteractorConeExample()
-
I have a strange warning in compilation with Sydney 10.4.1 that I just can't understand: procedure TWorkOrderListFrame.WorkOrderFilesGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var R: TRect; C: TColor; Value: string; Canvas: TCanvas; PenColor: TColor; BrushColor: TColor; FileIndex: Integer; Data: TWorkOrderData; BackgroundColor: TColor; WorkOrdersSelectedRow: Integer; begin // avoids any change at header row if ARow = 0 then Exit; // checks and gets work order data WorkOrdersSelectedRow := WorkOrdersGrid.Selection.Top; if FWorkOrderManager.GetWorkOrderDataByIndex(WorkOrdersSelectedRow - 1, Data) then // evaluates file index FileIndex := ARow - 1; if (FileIndex < 0) or (FileIndex >= TWorkOrderData.FILE_DATA_SIZE) then Exit; if Data.FileData[FileIndex].FileName = '' then Exit; // recovers canvas Canvas := WorkOrderFilesGrid.Canvas; [dcc64 Warning] osWorkOrderListFrame.pas(946): W1036 Variable 'FileIndex' might not have been initialized The line with the warning is: if (FileIndex < 0) or (FileIndex >= TWorkOrderData.FILE_DATA_SIZE) then Exit; but FileIndex is set just the line above.... Any idea ?
-
Variable might not have been initialized
shineworld replied to shineworld's topic in Delphi IDE and APIs
Normally I use only an internal GIT server (gitea). But this part of the source code was copied with WinMerge from a portable SSD which gave me a lot of issues and I've dismissed it recently. Thank you to all for support. -
Variable might not have been initialized
shineworld replied to shineworld's topic in Delphi IDE and APIs
ohhh I've checked... The pas file was corrupted, I've used WinMerge to copy some line in the past, and IDE shown text "then Exit" but compiler and copy/paste does not.... Fixed replacing all code and now works. So sorry..... -
Variable might not have been initialized
shineworld replied to shineworld's topic in Delphi IDE and APIs
Sorry but procedure TWorkOrderListFrame.WorkOrderFilesGridDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var R: TRect; C: TColor; Value: string; Canvas: TCanvas; PenColor: TColor; BrushColor: TColor; FileIndex: Integer; Data: TWorkOrderData; BackgroundColor: TColor; WorkOrdersSelectedRow: Integer; begin // avoids any change at header row if ARow = 0 then Exit; // checks and gets work order data WorkOrdersSelectedRow := WorkOrdersGrid.Selection.Top; if FWorkOrderManager.GetWorkOrderDataByIndex(WorkOrdersSelectedRow - 1, Data) then // evaluates file index FileIndex := ARow - 1; // <--- Here FileIndex is initialized with ARow (in update cell grid ROW) - 1 because first row is fixed row. if (FileIndex < 0) or (FileIndex >= TWorkOrderData.FILE_DATA_SIZE) then Exit; // <--- here the FileIndex is checked to be inner 0 to TWorkOrderData.FILE_DATA_SIZE - 1) otherwise exit (none to do). if Data.FileData[FileIndex].FileName = '' then Exit; // recovers canvas Canvas := WorkOrderFilesGrid.Canvas; Sincerely FileIndex, at if (FileIndex < 0.... ) it already "defined" but compling phase say "undefined"... -
Variable might not have been initialized
shineworld replied to shineworld's topic in Delphi IDE and APIs
I feel exactly the same way about Hint and Warnings, usually I've got 0/0. They are an indispensable tool to guarantee good code, especially when we are talking about millions of lines in play. At the moment I am compiling this project still with Sydney, although I also have Athens on which I have yet to test many third-party libraries that require more up-to-date versions and generate too many Warnings. -
I alternate with a colleague of mine in development with Athens on the same PC. As soon as Athens 12.1 patch 1 came out, I installed it using the manual procedure. Yesterday my colleague continued working on the same PC, and not knowing that I had already installed the patch manually, he also applied it with Get It, as he saw it in the list of possible updates. Now I find myself with two ways of installing the same patch and I wonder if this may lead to problems in the proper functioning of the environment. I would like to avoid re-installing the whole package and the 20 or so third-party libraries we use from scratch. Any idea whether we have "broken" the toy ?
-
I usually ask my questions about the Delphi code to ChatGPT 4. It is very fast and enougth precise. You can use same chat session to teach it when is wrong and it learn for next responses. Recently I've played with local AI using "ollama" and "mixtral" model for programming. Example in pastebin : https://pastebin.com/wWaLsw1V Mixtral model requires a lot of memory, I've 48GB in my PC, but I don't have a compatible CUDA GPU so will take 4 minutes to get the pastebin result using only I7 CPU.
-
Hi all. I'm trying to convert a layout from PySimpleGUI to DelphiVCL. All works fine but I was not able to put an image in an Image() component programmatically. 1] I get a frame from OpenCV VideoCamera cap with: self.__cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) ret, frame = self.__cap.read() 2] I convert the frame to a png image with: png_image = cv2.imencode('.png', frame)[1].tobytes() Now with PySimpleGUI I just update it with: view.window['image_1'].update(data=png_image) where image_1 = sg.Image(filename='', key='image_1', size=(640, 480)) With DelphiVCL I've created a image_1 = Image(self) and assigned basic parent and props but I don't find a way to update the img (an array of bytes with a PNG image inner). Thank you very much for suggestions.
-
Do you need an ARM64 compiler for Windows?
shineworld replied to Lars Fosdal's topic in Cross-platform
We bought industrial Iot licence version for 45 to 89€ depending by number an type of cores. W10 1908 version. It works very fine. I in will prepare a video next week. -
Do you need an ARM64 compiler for Windows?
shineworld replied to Lars Fosdal's topic in Cross-platform
I've already made 😉 RPI 4b running W10 which execute intel 64 bit native code. A very low cost operator interface for a CNC. Also Open GL works but remain the price of intel to arm just in time conversion. All for lees than 90€... All made with Delphi. An early video of first experiments but well working. https://youtu.be/3u0L4uaigV8?si=H5mApXT-ryQ3EbGc -
Do you need an ARM64 compiler for Windows?
shineworld replied to Lars Fosdal's topic in Cross-platform
A Windows ARM compiler could be interesting because W10/W11 can run in low-cost devices as like as Raspberry overall for kiosk or embedded user panels projects. -
In the past, I was in trouble with web installation so I always downloaded the full iso image.
-
Ok, I'm trying... Uninstall does not ask me anything but the new installation asks if to use an Already Existent License 😉 Before, however, I've clonezilled the C disk 🙂
-
So to get the new 12.1 I've to uninstall and reinstall all by zero? 1] I have got a lot of manually installed 3rd part libraries (13, ... uh...). 2] What happens with the Installation counter? Do they take into account that I've uninstalled it? 2nd question is important because I've two development PCs: 1] main office desktop PC to do work when I'm in the office. 2] A secondary portable notebook to do work when I'm at the customer's factory They are used mutually exclusive, or 1 or 2, but I've already used 2 installations shoots.
-
Will be available as GetIt update ?
-
Do you need an ARM64 compiler for Windows?
shineworld replied to Lars Fosdal's topic in Cross-platform
In my case would be amazing to have a valid Delphi compiler for ARM64 Linux + FMX. A lot is moving in the embedded world based on ARM architectures + Linux and I've also tried FPC + Lazarus (a nightmare...). Dreams are dreams 🙂