

dormky
Members-
Content Count
155 -
Joined
-
Last visited
Community Reputation
5 NeutralRecent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
-
Main bottleneck is the repeated calls to the gdi canvas to draw lines. I have code that prevents drawing unnecessarily (ie check if 2 points are far enough apart that they won't get resolved to the same coordinates) and this reduces the time proportionally to the size of the canvas used.
-
Would TeeChart allow me to draw arbitrary shapes onto the graph ? From what I've this doesn't seem to be the case but I might have missed something. I need complete control over how the axis are laid out etc. Although if you know what exactly TeeChart uses under the hood that might point me in the right direction.
-
Quickly yes, quickly enough no. And I'm already using things like Polyline and caching to reduce syscalls.
-
I did, but performance wasn't that much better, only 50 % 😕 And that's discounting a bunch of issues I've had making it work (it's still not a one-to-one of what I get with GDI, while OpenGL is and didn't cause me implementation issues)
-
I'm drawing custom graphs, for now using GDI. Here's an example from a test project : It's a mess but that's because I'm testing as many possibilities as I can with the management of the axis. One problem that I'm running into is performance : 50ms to draw. This is annoying because it makes the graph jittery when dragging elements (lines and rectangles must be able to be moved by the user). I've made modifications so that it can be rendered by OpenGL, which is obviously MUCH faster (<8ms without looking very much at other performance improvements). Unfortunately initializing OpenGL takes multiple seconds. This is fine when you're running a game, but I have forms with 12 of these graphs on screen at the same time, all showing different stuff... So yeah. Is there any rendering engine on Windows that's got equivalent functionnality to GDI, but is just faster by vertue of using the GPU ? Any alternatives to consider ?
-
query := TMyQuery.Create(nil); query.Connection := conn; query.SQL.Text := 'INSERT INTO documents (key, document) VALUES (:pkey, :pdocument)'; query.ParamByName('pkey').Value := 'key'; query.ParamByName('pdocument').AsBytes := TFile.ReadAllBytes('dummy_1.pdf'); query.Execute(); query.Free(); CREATE TABLE `documents` ( `key` VARCHAR(255) NOT NULL, `document` MEDIUMBLOB); The pdf file : https://www.cte.iup.edu/cte/Resources/PDF_TestPage.pdf For some reason, without the key field this works perfectly fine, but with it I get the error : EMySqlException with message '#42000You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key, document) VALUES ('key', '%PDF-1.4\n%äüöß\n2 0 obj\n<</Length 3 0 R/Fil' at line 1'. Does anyone have any idea of what forsaken bullshit is going on ? It doesn't look like an escape character issue AFAIK as the problem occurs whether the key parameter is in front of the document parameters or after it. I think it's because delphi is casting the pdf file as text but I'm not sure. Edit : I'm blind. Since MyDAC forces you to write SQL statements by hand, I forgot about the `. Gotta hate on bad error messages 🙂
-
You mean that MySQL can transfer data directly from one server to the other ? I'm not talking about doing replication, this is for select rows
-
The databases aren't on the same server. Obviously if that was the case this would be trivial
-
So I need to copy the contents of one table to another database. But it seems changing the Connection on a TMyQuery erases the data stored in it. Any alternatives that do not require creating a TMyTable ?
-
Figured that anonymous methods on instance procedures such as OnClick was actually possible with this little tick : type // Allows instance anonymous procs by giving it to the constructor here and giving OnSender to the OnClick event for example // You need to give the instance on which the OnSender will be attributed so the object gets garbage-collected. // MyButton.OnClick := TAnonProc.Create(MyButton, procedure (Sender: TObject) begin /* */ end).OnSender; TAnonProc = class(TComponent) proc: TProc<TObject>; constructor Create(AOwner: TComponent; AProc: TProc<TObject>); reintroduce; procedure OnSender(Sender: TObject); end; constructor TAnonProc.Create(AOwner: TComponent; AProc: TProc<TObject>); begin inherited Create(AOwner); proc := AProc; end; procedure TAnonProc.OnSender(Sender: TObject); begin if Assigned(proc) then proc(Sender); end;
-
Ended up landing on this, works fine for my purpose : procedure AssertFloat(const value, should: Extended); begin Assert(Abs(value - should) < 0.00001); end;
-
Consider : procedure Test(); var number: single; begin number := 0.96493138416; // Too long for a single precision // Assert(number = 0.96493138416); // Will fail, normal number := RoundTo(number, -3); Assert(number = 0.965); Fails end; Here number is supposed to be a value I'm getting from the data I'm running the test on. Due to binary representation the number will never be exactly correct, however trying to Assert with the value given by the debugger doesn't work either. So how am i meant to assert on floats ? Thanks.
-
How to combine two methods with the same structure using RTTI?
dormky replied to bravesofts's topic in Algorithms, Data Structures and Class Design
This is related : https://stackoverflow.com/questions/4652958/is-there-a-way-to-log-every-gui-event-in-delphi I wrote this unit based on it, it might give you ideas. Note that this is not perf-tested and is probably quite bad in that regard with all the looping of rtti info. Also might crash if you have cases I have not covered when interpreting RTTI. unit UEventLogger; // See https://stackoverflow.com/questions/4652958/is-there-a-way-to-log-every-gui-event-in-delphi // Call TEventLogger.AddEventInterceptors in every FormCreate. // Since TEventLogger is a compnent, it gets destroyed when his parent gets destroyed. interface uses EEvents, EException, Classes, Controls, Generics.Collections, Rtti; type OnEventLoggerEvent = reference to procedure(const event: string; const controlName: string); TEventLogger = class(TComponent) private EventName: string; originalEvent: TNotifyEvent; procedure HandleEvent(Sender: TObject); constructor Create(Control: TControl; EventName: string; originalEvent: TNotifyEvent); class procedure RecurseControls(Control: TControl; ExaminedControls: TList<TControl>; context: TRttiContext); public class procedure AddEventInterceptors(Control: TControl); class procedure RegisterEurekaLogWriter(); class var logs: TArray<string>; class var OnEvent: OnEventLoggerEvent; end; implementation uses TypInfo, SysUtils, Windows; type TStupidEL = class procedure OnReproduceRequest(AExceptionInfo: TEurekaExceptionInfo; var AReproduceText: String; var ACallNextHandler: Boolean); end; var h: TStupidEL; constructor TEventLogger.Create(Control: TControl; EventName: string; originalEvent: TNotifyEvent); begin inherited Create(Control); self.EventName := EventName; self.originalEvent := originalEvent; end; procedure TEventLogger.HandleEvent(Sender: TObject); begin // Log the event : datetime - event name - control name logs := logs + [FormatDateTime('dd/mm/yy hh:nn:ss.zzz', Now()) + ' - HandleEvent ' + EventName + ' on ' + (Sender as TControl).Owner.Name+'.'+(Sender as TControl).Name]; if Assigned(OnEvent) then OnEvent(EventName, (Sender as TControl).Owner.Name+'.'+(Sender as TControl).Name); // Forward to the original handler originalEvent(Sender); end; class procedure TEventLogger.RecurseControls(Control: TControl; ExaminedControls: TList<TControl>; context: TRttiContext); var theTypeInfo: TRttiInstanceType; theProperty: TRttiProperty; interceptor: TEventLogger; theEvent: TNotifyEvent; theValue: TValue; field: TRttiField; newControl: TControl; instanceType: TRttiInstanceType; begin ExaminedControls.add(Control); theTypeInfo := context.GetType(Control.ClassInfo) as TRttiInstanceType; for theProperty in theTypeInfo.GetProperties do begin if (not theProperty.IsWritable) then continue; if (not (theProperty.PropertyType.ToString.StartsWith('TNotifyEvent'))) then continue; if (theProperty.Name = 'OnClick') or (theProperty.Name = 'OnDblClick') then begin theValue := theProperty.GetValue(Control); theEvent := nil; if not theValue.IsEmpty then theEvent := theValue.AsType<TNotifyEvent>(); if Assigned(theEvent) then begin interceptor := TEventLogger.Create(Control, theProperty.Name, theEvent); theProperty.SetValue(Control, TValue.From<TNotifyEvent>(interceptor.HandleEvent)); end; end end; try for field in theTypeInfo.GetFields do begin if field.name.StartsWith('F') then continue; // All the private F fields ; we're only interested in our boutons and things like that. if field.FieldType = nil then continue; // Undefined types, like pointers (^TQCTestAll) if field.FieldType.TypeKind = tkClass then begin instanceType := field.FieldType As TRttiInstanceType; if instanceType.MetaclassType.InheritsFrom(TControl) then begin newControl := nil; theValue := field.GetValue(Control); if not theValue.IsEmpty then newControl := theValue.AsType<TControl>; if Assigned(newControl) then if not ExaminedControls.Contains(newControl) then RecurseControls(newControl, ExaminedControls, context); end; end; end; except on E: EAccessViolation do // For some reason we can get an AccessViolation while looping through the fields. Seemed to happen // on ParentControl. end; end; class procedure TEventLogger.AddEventInterceptors(Control: TControl); var examinedObjects: TList<TControl>; begin examinedObjects := TList<TControl>.Create(); TEventLogger.RecurseControls(Control, examinedObjects, TRttiContext.Create()); examinedObjects.Free; end; procedure TStupidEL.OnReproduceRequest(AExceptionInfo: TEurekaExceptionInfo; var AReproduceText: String; var ACallNextHandler: Boolean); begin AReproduceText := sLineBreak + String.join(sLineBreak, TEventLogger.logs); TEventLogger.logs := []; end; class procedure TEventLogger.RegisterEurekaLogWriter(); begin RegisterEventReproduceRequest(h.OnReproduceRequest); end; end. -
If you're open-source, you need to sell something else (training, resources, support, etc...)
-
Can the UI be updated in any way while the main thread is doing work ?
dormky replied to dormky's topic in VCL
I'm 100% agreeing with you. Management doesn't. Management wants a pretty loading icon without actually putting in the work 🙂 Imo the windows cursor does a perfectly fine job, we're talking ~10s loading time here.