Podczas zmiany wielkości okna, musi ono zostać przerysowane w czasie rzeczywistym (zmiana rozmiaru choćby o 1 piksel oznacza konieczność przerysowania większości elementów formy, których wielkość musi być zawsze dopasowana do rozmiaru okna).
Robienie tego przez Canvas zda egzamin, czy to zbyt duże marnotrawstwo pod względem wydajności?
To zależy od ilości elementów do narysowania i oczywiście od kodu, który to rysowanie wykonuje;
Jeżeli formularz ma mieć prosty wygląd, np. kilka linii plus jednokolorowe wypełnienie, to spokojnie możesz używać metod klasy TCanvas
; Tylko że Twoje podejście opisane wcześniej, nie jest najlepsze; Jeśli formularz ma mieć ramkę z kilku jednopikselowych linii różnego koloru, to nie maluj dla każdej linii prostokąta, np. metodą Rectangle
, bo się to nie opłaca; Malowałbyś w kółko całe płótno okna, co jest stratą czasu;
Sam teraz parcuję nad aplikacją z własnym i niezależnym od systemu i ustawionego schematu interfejsem, używając do tego celu formularza bez obramowania; Na to kładę sobie komponent dziedziczący po TGraphicControl
, który "symuluje" obramowanie okna; W jego nadpisanej metodzie Paint
rysuję za pomocą Rectangle
zewnętrzną ramkę i wypełnienie, następnie ramkę poświaty metodą FrameRect
(aby namalować samą ramkę, bez wypełnienia), następnie za pomocą Rectangle
maluję wewnętrzną ramkę plus wypełnienie na biało "klienta", a na koniec metodą FrameRect
wewnętrzną ramkę poświaty i przez Pixels
przejście z poświaty do koloru wypełnienia obramowania; Przykład:
Całość rysowana jest na tyle szybko, że nawet jak dodam na formularz różne inne komponenty, to podczas rozciągania nic nie migocze; A mój sprzęt jest naprawdę powolny - 1,13GHz
procesor i 48MiB
na grafice często nie wystarcza; Ale z drugiej strony wiem, że na współczesnych komputerach wszystko będzie działać płynnie, skoro i u mnie tak działa;
Wiem, że w większości przypadków ScanLinie jest bardziej wydajny, ale co np. z rysowaniem linii prostych w pionie? Np. ramka okalająca moje okno formy składa się z 5 różnokolorowych pasków o grubości 1 pixela (taki jakby gradient). Przy zmianie rozmiaru okna, ramka będzie musiała zostać przerysowana na nowo. W poziomie ScanLine jest idealny, ale w pionie?
Wiele to nie zmienia;
Jeżeli chcesz narysować linię w poziomie, to wystarczy jeden ScanLine
i uzupełnienie kolejnych komórek w konkretne wartości; W przypadku malowania linii w pionie - musisz dla każdego wiersza użyć ScanLine
aby otrzymać pointer na pierwszą komórkę wiersza, a następnie skorzystać z odpowiedniego indeksu, aby dostać się do konkretnej komórki piksela; Czyli nadal będzie to jedna pętla, tyle że ScanLine
będziesz musiał wywoływać w każdej jej iteracji;
Obstawiam, że to rozwiązanie będzie szybsze od metody Line
, ale nie aż na tyle, aby było się czym przejmować;
A jeżeli w Canvasie, to jaka metoda? Pixels w pętli?
Pixels
służy do odczytu/modyfikacji pojedynczego piksela, więc jedynie w takich przypadkach opłaca się z niego skorzystać; Użycie tej właściwości do malowania linii czy prostokątów jest najwolniejsze z możliwych, więc już lepiej użyć Line
czy MoveTo + LineTo
;
Rectangle (rysowałbym 5 prostokątów jeden na drugim, każdy o 1 px mniejszy od poprzedniego. Za jednym zamachem powstałaby cała ramka)?
To tutaj o tym pisałeś;
Rectangle
powinno się używać tylko i wyłącznie w przypadku, gdy potrzeba narysować prostokąt z obramowaniem o innym kolorze, niż wypełnienie - w każdym innym przypadku jest to nadmiarowe; Ty potrzebujesz narysować pięć ramek o róznych kolorach i o grubości 1px
, więc Rectangle
możesz użyć raz (aby dodatkowo wypełnić kolorem formularz), a pozostałe linie ramki namaluj za pomocą FrameRect
;
A może warto zastosować rozwiązanie jak np. w windowsowym Paincie? To znaczy w momencie zmiany rozmiaru płótna nie widzimy tego w czasie rzeczywistym, ale pojawia się taka przerywana ramka wyznaczająca jego nową wielkość.
Zauważ, że typ odświeżania wnętrza formularza określają ustawienia systemowe, więc implementując rozciąganie w typowy sposób - i tak nic nie zmienisz; Ja mam wyłączone pokazywanie zawartości formularza podczas przeciągania i rozciągania, więc zawsze widzę jedynie samą ramkę, aż do czasu puszczenia LPM;
Aby uniezależnić styl odświeżania zawartości okna, musiałbyś albo grzebać w ustawieniach systemowych, albo to rozciąganie zaimplementować w nietypowy sposób, na który ustawienia systemowe nie wpływają; Sugeruję więc zawsze przemalowywać całe okno, a typ jego aktualizowania pozostawić do wyboru użytkownikowi (co ustawi w systemie, to będzie miał);
Ogólnie to pamiętaj, aby jak najmniej pikseli przerysowywać wielokrotnie; Czasem zamiast używać kilku Line
, lepiej jest użyć FrameRect
, a zamiast Rectangle
np. FillRect
.