Компонент Timage

Тема в разделе "Delphi - Multimedia, Графика, Игры", создана пользователем liones, 9 ноя 2012.

  1. liones

    liones New Member

    Регистрация:
    25 фев 2009
    Сообщения:
    3
    Симпатии:
    0
    Добрый день!
    Вопрос такой: пользователь хочет менять рисунок на форме. На форму поместила timage и написала процедуру:
    Код (Text):
    procedure TGlav.Image1DblClick(Sender: TObject);
    begin
    if Glav.OpenPictureDialog1.Execute then
    begin
    //загружаем выбранный рисунок
    Glav.Image1.Picture.LoadFromFile(Glav.OpenPictureDialog1.FileName);
    Glav.Image1.Show; //отображем рисунок на форме
    end;
    end;
    НО после закрытия программы этот рисунок не сохраняется, т.е. при каждом открытии нужно снова выбирать рисунок.
    Что еще нужно дописать чтобы исправить эту проблемку?
     
  2. nayke

    nayke Well-Known Member

    Регистрация:
    4 авг 2010
    Сообщения:
    310
    Симпатии:
    0
    Можно копировать рисунок в папку с программой и подгружать при открытии.
     
  3. sinkopa

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    Хм... Ну можно конечно и так... Только вот придется заморачиваться на тему удалять ненужные файлы.
    Пользователь может десяток другой рисунков сменить за время сеанса... так ведь? :)
    А еще они могут быть разные каждый раз... ICO, BMP, WMF и пр...
    Гораздо "элегантней" просто запомнить состояние Timage на выходе
    Код (Delphi):
    procedure TGlav.FormClose(Sender: TObject; var Action: TCloseAction);
    var
    m: TMemoryStream;
    stored: string;
    begin
    m := TMemoryStream.Create;
    m.WriteComponent(Glav.Image1);
    m.Position := 0;
    stored := ChangeFileExt(Application.ExeName,'.store');
    m.SaveToFile(stored);
    m.Free;
    end;
    а на загрузке приложения его восстановить
    Код (Delphi):
    procedure TGlav.FormCreate(Sender: TObject);
    var
    m: TMemoryStream;
    stored: string;
    begin
    stored := ChangeFileExt(Application.ExeName,'.store');
    if not FileExists(stored) then
    Exit;

    m := TMemoryStream.Create;
    m.LoadFromFile(stored);
    m.Position := 0;
    m.ReadComponent(Glav.Image1);
    m.Free;
    end;
    По моему так... :)
     
  4. nayke

    nayke Well-Known Member

    Регистрация:
    4 авг 2010
    Сообщения:
    310
    Симпатии:
    0
    Формат файла особо роли не играет. Фал можно удалять при выборе нового - тогда будет всегда 1 актуальный.
    В этом запись на диск будет происходить только при смене темы оформления.
    А в вашем случае запись будет происходить постоянно при закрытие формы. А если форма не главная? и открывается по 10 раз при работе в системе.
    Или скажем пользователь открыл 2 формы с фоновым рисунком. На первой перевыбрал фон. Закрыл первую, а затем вторую - итог изменения не сохранятся.
     
  5. sinkopa

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    Уважаю людей упертых... даже заблуждающихся... :)
    Формат файла как раз роль и играет...
    Если Вы использовали в своих проектах TImage, то Вы знаете что свой внутренний тип (TGraphic) TImage рождает именно на основе расширения файла.
    Т.е. нельзя обозвать "imgstored.BMP" в какой нибуть "imgstored.BIN" а потом загрузить TImage.
    Или Вы предлагаете проверять на наличие файла ВСЕХ поддерживаемых расширений с именем "imgstored.*"?
    Поэтому:
    Допустим пользователь выбрал "image1.ico" а потом поменял на "image2.bmp".
    Допустим Вы копируете их в папку с проектом, с именем "imgstored.*"
    В "Вашем" случае необходимо:
    1) Удалить "imgstored.ICO" и записать на его место "imgstored.BMP"
    2) Запомнить (где нибудь) что на следующем запуске нужно загрузить "imgstored.BMP"
    3) При запуске узнать (как нибудь) что нужно загрузить "imgstored.BMP" а не "JPG" какой нибудь...
    Да хоть сто... :)
    В "моем" случае, "ваши вопросы" решаются одним флагом.
    Код (Delphi):
    var
    ImgChanged: Boolean;
    //...
    if ImgChanged then
    begin
    //... сохраняем...
    ImgChanged := False;
    end;
    Ну... или ( раз Вы все еще настаиваете :) ) действительно сохранить состояние (НЕ ФАЙЛ) TImage непосредственно в момент смены изображения.
    Хотя... если Вы внимательно присмотритесь к коду поста родившего данную тему... то там речь шла о конкретной форме (переменная Glav) и конкретном TImage на этой форме.
     
  6. nayke

    nayke Well-Known Member

    Регистрация:
    4 авг 2010
    Сообщения:
    310
    Симпатии:
    0
    Ну давайте считать 1:1)) решение наверное возможно и то и то.

    Я, помнится, в delphi делал так:
    - Формировал папку(например CSS). Либо хранил в БД.
    - При запуске приложения подгружал графические файлы - по имени без учета расширения.
    - Реестр файлов хранил в Файле с темой, Файлы подменял при смене темы или конкретного файла.

    Есть минусы есть плюсы, но
    - дополнительная обработка не требуется(флаг - это хорошо, но что если таких картинок 50?),
    - нет ограничений - в какой бы последовательности человек формы не закрывал, какие бы операции не проводил - конфликтов не возникает.
     
  7. sinkopa

    sinkopa Well-Known Member

    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    ;) пусть будет ничья...
    Я собственно и не собирался соревнование устраивать...
    Просто есть в Delphi придуманные программистами Borland/Embarcadero "фичи", которые на первый взгляд неочевидны (если не читать исходники)...
    К примеру, тот же самый ReadComponent, происходит неявно всегда когда рождается любая VCL форма (грузится из DFM)...
    И уж если "большие дядьки" считают что это быстро и безопасно, то и я не вижу причин, почему нам (программистам) не использовать те же методики... :)

    Вот, на вскидку усовершенствовал "мой" подход. Учел так сказать Ваши "замечания".
    Получилось (на мой взгляд) более универсально и даже проще с точки зрения использования.
    (1) Пишем класс (файл юнита "uStoreImageList.pas")
    Код (Delphi):
    unit uStoreImageList;

    interface

    uses
    SysUtils, Classes, Forms, ExtCtrls, Contnrs;

    type
    TImagesStore = class(TObjectList)
    private
    FStoreFile: string;
    public
    constructor Create(StoreFile: string);
    { Добавляет в StoreList произвольный TImage }
    procedure AddToStoreList(Image: TImage); overload;
    { Добавляет в StoreList все TImage указанной формы }
    procedure AddToStoreList(Form: TForm); overload;
    { Сохраняет StoreList в файл с именем FStoreFile }
    procedure StoreImages;
    { Восстанавливает состояния всех TImage из StoreList из файла с именем FStoreFile }
    procedure RestoreImages;
    { Более безопасный метод восстановления, но чуть чуть более медленный }
    procedure SafeRestoreImages;
    end;

    implementation

    { TImagesStore }

    constructor TImagesStore.Create(StoreFile: string);
    begin
    inherited Create(False);
    FStoreFile := StoreFile;
    end;

    procedure TImagesStore.AddToStoreList(Image: TImage);
    begin
    if (IndexOf(Image) < 0) then // исключает дубликаты
    inherited Add(Image);
    end;

    procedure TImagesStore.AddToStoreList(Form: TForm);
    var
    i: Integer;
    img: TImage;
    begin
    for i := 0 to Form.ComponentCount-1 do
    if (Form.Components[i] is TImage) then
    begin
    img := Form.Components[i] as TImage;
    AddToStoreList(img);
    end;
    end;

    procedure TImagesStore.RestoreImages;
    var
    m: TMemoryStream;
    i: Integer;
    img: TImage;
    begin
    if (Count < 1) or (not FileExists(FStoreFile)) then
    Exit;

    m := TMemoryStream.Create;
    try
    m.LoadFromFile(FStoreFile);
    m.Position := 0;

    for i := 0 to Count - 1 do
    if (m.Position < m.Size) then
    begin
    img := TImage(Self[i]);
    m.ReadComponent(img);
    end;
    finally
    m.Free;
    end;
    end;

    procedure TImagesStore.StoreImages;
    var
    m: TMemoryStream;
    i: Integer;
    img: TImage;
    begin
    if (Count < 1) then
    Exit;
    m := TMemoryStream.Create;
    try
    for i := 0 to Count - 1 do
    begin
    img := TImage(Self[i]);
    m.WriteComponent(img);
    end;
    m.Position := 0;
    m.SaveToFile(FStoreFile);
    finally
    m.Free;
    end;
    end;

    procedure TImagesStore.SafeRestoreImages;
    var
    m: TMemoryStream;
    i: Integer;
    img: TImage;
    pos: Integer;
    begin
    if (Count < 1) or (not FileExists(FStoreFile)) then
    Exit;

    m := TMemoryStream.Create;
    try
    m.LoadFromFile(FStoreFile);
    m.Position := 0;
    img := TImage.Create(nil);

    while (m.Position < m.Size) do
    begin
    pos := m.Position;
    m.ReadComponent(img);

    for i := 0 to Count - 1 do
    if (img.Name = TImage(Self[i]).Name) then
    begin
    m.Position := pos;
    m.ReadComponent(TImage(Self[i]));
    end;
    end;
    img.Free;
    finally
    m.Free;
    end;
    end;

    end.
    (2) Добавляем данный модуль в проект.
    (3) Открываем в редакторе файл проекта (.DPR) и добавляем код
    Код (Delphi):
    program MyTestApp;

    uses
    Forms, SysUtils,
    uStoreImageList in 'uStoreImageList.pas', // (1) Добавили модуль

    Unit1 in 'Unit1.pas' {Glav},
    Unit2 in 'Unit2.pas' {Form2};

    {$R *.res}
    var
    Ims : TImagesStore;  // (2) Добавили переменную

    begin
    Application.Initialize;
    Application.CreateForm(TGlav, Glav);
    Application.CreateForm(TForm2, Form2);

    Ims := TImagesStore.Create(ChangeFileExt(Application.ExeName,'.store'));

    // (3) Добавили Image1 с формы Glav
    Ims.AddToStoreList(Glav.Image1);
    // (4) Добавили ВСЕ 150 :-) картинок с формы Form2
    Ims.AddToStoreList(Form2);

    // (5) Восстановили состояние
    Ims.SafeRestoreImages; //Ims.RestoreImages;
    Application.Run;
    // (6) Сохранили состояние
    Ims.StoreImages;
    Ims.Free;
    end.
    Вот... по моему так :)
     
  8. nayke

    nayke Well-Known Member

    Регистрация:
    4 авг 2010
    Сообщения:
    310
    Симпатии:
    0
    Ну я при решении исходил скорее из прикладной логики кнопок.
    Класс конечно не найду, но отличие в том, что скажем:

    Есть кнопка Accept - она едина на всех формах.

    В Вашем решении при наличии 20 форм она сохранится 20 раз(а у кнопки обычно еще и несколько состояний хранится).
    Также собственно при замене вида этой кнопки на одной форме пришлось бы менять вручную на всех и переписывать весь файл темы.
    Т.е. завершение приложения неоптимально.. и если скажем в момент записи программа завернется аварийно - потеряем весь интерфейс.

    То же самое про чтение. Если элементов дизайна много, то чтение всего массива будет долгим и утомлять пользователя при запуске программы.

    Я же делал(скажу честно писал давно и всех тонкостей не вспомню) примерно так:
    1. При запуске приложения(формы) определяем логические атрибуты(элементы класса - кнопка, фон, место игрока).
    2. Грузить графические файлы для этих элементов и потом пихаем их в Image.
    3. при смене, сохраняем изменения для данного логического атрибута.

    Таким образом
    1. Запись и чтение локализовано на один элемент.
    2. Какие элементы грузить можно раскидать на приложение в целом(для основных элементов), либо на создание конкретной формы(если ее все равно отрисовывать динамически или она вызывается редко)
    3. И скажем при смене дизайна кнопки пользователь ждет, что будет задержка. А долгое завершение программы для него ошибка)

    Вт как-то так)
     
Загрузка...

Поделиться этой страницей