Доступ к StringGrid из другой формы

Отредактируйте тело для более подробной информации.

У меня есть форма под названием ENP, определенная в модуле EnpView. Форма ENP создается и отображается из события обработчика щелчка по элементу панели инструментов в главной форме (TPrincipal).

procedure TPrincipal.ENP1Click(Sender: TObject);
begin
  TENP.Create(self).Show();
end;

Форма enp знает (в публичном объявлении) сообщение clearGrid().

Форма ENP имеет TStringGrid с именем StringGrid. И кнопка называется "Добавить". При нажатии кнопки "Добавить" создается и отображается другая форма: Форма AddEnp, определенная в модуле EnpViewAdd.

procedure TENP.opAgregarClick(Sender: TObject);
begin
  TAddEnp.Create(self).Show();
end;

Форма AddEnp, есть любые TEdits. Значения входных данных должны быть добавлены в EnpView.StringGrid.

Я пытаюсь это:

implementation

uses
  EnpView, Main;
procedure TAddEnp.AgregarClick(Sender: TObject);
begin

  { Agrego el nodo xml }
  Globals.Xml.agregarMuestra(muestra.Text);
  Globals.Xml.insertEnp(muestra.Text,golpes.Text,metros.Text);

  { Send messages to EnpView Form }
  ENP.clearGrid();
  ENP.populateGrid();

end;

Сообщения ClearGrid завершаются сбоем в строке 1 с нарушением прав доступа:

procedure TENP.clearGrid();
begin
  Self.StringGrid.RowCount := 2;
  Self.StringGrid.Rows[1].Clear();
end;

Методы clearGrid работают, если они отправлены внутри класса. Есть идеи?.

2 ответа

Решение

Создайте свойство с именем, например, ENPForm в TAddENP и назначьте форму ENP сразу после ее создания. Объявите это следующим образом:

TAddENP = class(TForm)
private
  FENPForm: TENP;

// all of your already existing declarations

public
  property ENPForm: TENP read FENPForm write FENPForm;
end;

Теперь, когда у вас есть возможная ссылка на форму ENP, вы можете использовать ее по своему усмотрению.

При создании формы TAddENP сделайте следующее:

procedure TENP.opAgregarClick(Sender: TObject);
var
  addForm: TAddENP;
begin
  addForm := TAddEnp.Create(Self);
  addForm.EnpForm := Self;
  addForm.Show;
end;

Теперь вы создали вторую форму и дали ей безопасную ссылку на первую. Теперь они могут безопасно общаться друг с другом.

Я советую вам избегать того, чтобы одна форма работала с компонентами другого, потому что это увеличивает зависимость между ними. Вместо этого объявите для этого открытые методы, чтобы формы зависели от их интерфейсов, а не от их реализаций.

Надеюсь, это поможет.

Из вашего вопроса (я добавил code-style чтобы было понятнее)

У меня есть форма называется ENP, определенный в EnpView Блок. ENP форма, создается и отображается из события обработчика щелчка элемента панели инструментов в главной форме (TPrincipal).

procedure TPrincipal.ENP1Click(Sender: TObject);
begin
  TENP.Create(self).Show();
end;

Это ничего не делает с вашим ENP переменная формы.
Вы создаете экземпляр TENP сформировать класс и показать его, используя Show, но ENP переменная не назначена.
Вы не можете назначить экземпляр ENP переменная, так как каждое нажатие кнопки создает новый экземпляр (так что у вас есть несколько экземпляров TENP) вокруг.

Затем вы создаете запутанную зависимость TAddEnp экземпляр и (никогда ENP переменная).
Вы делаете это, создавая TAddEnp экземпляр (почему TAddEnp здесь, а не TAddENP?) показать это используя Show (давая пользователям возможность вернуться к TENP экземпляр и снова нажмите на opAgregar кнопка, чтобы создать больше экземпляров TAddEnp):

procedure TENP.opAgregarClick(Sender: TObject);
begin
  TAddEnp.Create(self).Show();
end;

Затем следует TAddEnp зависит от ENP переменная:

procedure TAddEnp.AgregarClick(Sender: TObject);
begin
//...
  ENP.clearGrid();
  ENP.populateGrid();
end;

Это действительно потерпит неудачу:

Сообщения ClearGrid завершаются сбоем в строке 1 с нарушением прав доступа:

procedure TENP.clearGrid();
begin
  Self.StringGrid.RowCount := 2;
  Self.StringGrid.Rows[1].Clear();
end;

Причина в том, что ENP не назначен (по умолчанию это будет nil) так внутри clearGrid, Self также будет nil,

Решения, которые вы могли бы реализовать

  1. Держите один экземпляр TENP а также TAddEnp вокруг, используя ShowModal заставить модальность запретить пользователю нажимать на одни и те же кнопки несколько раз.
  2. Оставьте свой существующий Show поведение, но обязательный каждый TAddEnp экземпляр к TENP Экземпляр, из которого он был создан.

Для первого решения ваш код станет таким:

procedure TPrincipal.ENP1Click(Sender: TObject);
begin
  ENP := TENP.Create(Application);
  ENP.ShowModal();
  ENP.Release();
  ENP := nil;
end;

а также

procedure TENP.opAgregarClick(Sender: TObject);
begin
  AddEnp := TAddEnp.Create(Application);
  AddEnp.ShowModal();
  AddEnp.Release();
  AddEnp := nil;
end;

Второе потребует больше усилий, так как вам необходимо предотвратить использование существующих переменных.

  • Удалить ENP переменная.
  • Удалить AddENP переменная.

Исправить self -> Self в методах

procedure TPrincipal.ENP1Click(Sender: TObject);
begin
  TENP.Create(Self).Show();
end;

а также

procedure TENP.opAgregarClick(Sender: TObject);
begin
  TAddEnp.Create(Self).Show();
end;

Здесь добавьте зависимость:

procedure TAddEnp.AgregarClick(Sender: TObject);
var
  ENP: TENP;
begin
//...
  ENP := Owner as TENP; // Owner will be of type TENP because of the Create(Self) in the ENP1Click method
  ENP.clearGrid();
  ENP.populateGrid();
end;
Другие вопросы по тегам