Пользовательская кнопка, унаследованная от TButton, не отображается

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

С приведенным ниже кодом как на мобильных устройствах, так и на настольных компьютерах (с использованием новых приложений по умолчанию в Delphi XE6) создание tTestButton1 работает нормально, но tTestButton2 не отображается в форме. Как это возможно?

type
tTestButton1 = class(TButton);
tTestButton2 = class(tTestButton1);

tMainForm = class(TForm)
private
  fTestButton: TButton;
public
  constructor Create(aOwner: TComponent); override;
end;

constructor tMainForm .Create(aOwner: TComponent);
begin
  inherited;

//  fTestButton := tTestButton1.Create(Self); // this works fine (used instead of next line)
  fTestButton := tTestButton2.Create(Self);  //this button does not show up
  fTestButton.Text := 'Test';
  fTestButton.Parent := Self;
  fTestButton.Visible := True;
  fTestButton.Position.X := 20;
  fTestButton.Position.Y := 20;
end;

person Hans    schedule 16.09.2014    source источник
comment
+1 отличный вопрос, замечательный репродукционный код, если бы все было так хорошо   -  person David Heffernan    schedule 16.09.2014
comment
Можно воспроизвести то же самое в Delphi XE3.   -  person TLama    schedule 16.09.2014
comment
И ХЕ7. Похоже на ошибку FMX, хотя трудно поверить, что это может быть так ......   -  person David Heffernan    schedule 16.09.2014
comment
Это по дизайну. Визуальный компонент должен иметь зарегистрированный стиль. В противном случае он не будет показан. Внутри компилятор ищет только первый производный класс.   -  person LU RD    schedule 16.09.2014
comment
Он появляется, если вы называете производный класс TButton!! Так что, возможно, обходной путь заключается в том, что вы даете всем своим производным кнопкам одно и то же имя класса!! Ха-ха!   -  person David Heffernan    schedule 16.09.2014
comment
@LURD Так почему прямой подкласс TButton в порядке, но не внук?   -  person David Heffernan    schedule 16.09.2014
comment
@DavidHeffernan, он может найти ButtonStyle в первом примере, но не во втором, где TestButton1Style не зарегистрирован.   -  person LU RD    schedule 16.09.2014
comment
@DavidHeffernan, это обсуждается здесь, codeverge. com/embarcadero.delphi.firemonkey/.   -  person LU RD    schedule 16.09.2014
comment
Хотелось бы, чтобы Embarcadero выбрала для показа хоть что-то на экране, когда стиль не был найден. Это действительно непредсказуемое поведение, когда элемент управления полностью исчезает. Потребовалось много часов отладки, чтобы локализовать проблему в простом коде выше. Я бы хотел, чтобы я мог использовать их продуктивно вместо этого ...   -  person Hans    schedule 17.09.2014


Ответы (1)


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

Но это разумный объем работы, и я полагаю, что все, что вы действительно хотите сделать, это организовать использование элемента управления в том же стиле, что и TButton. Добейтесь этого так:

type
  TButtonBase = class(TButton)
  protected
    function GetDefaultStyleLookupName: string; override;
  end;

function TButtonBase.GetDefaultStyleLookupName: string;
begin
  Result := 'Buttonstyle';
end;

Теперь выведите свои классы из TButtonBase.

type
  tTestButton1 = class(TButtonBase);
  tTestButton2 = class(tTestButton1);

Вместо того, чтобы искать стили на основе имени класса элемента управления, классы, производные от TButtonBase, будут использовать стиль с именем Buttonstyle.

person David Heffernan    schedule 16.09.2014
comment
В реальном коде я установил StyleLookup в конструкторе tTestButton1, и теперь оба класса отображаются в форме как кнопки. Хорошо, когда есть простое решение проблемы :-) - person Hans; 16.09.2014
comment
@Hans Это почти то, что я предложил. Я вставил дополнительный класс TButtonBase, чтобы дать вам возможность создавать другие классы кнопок, если вы хотите это сделать. Но, возможно, tTestButton1 уже был этим базовым классом. Я ценю, что вы упростили реальный код до небольшого и простого воспроизведения, чтобы задать вопрос. И еще раз я не могу похвалить вас более высоко за это. - person David Heffernan; 16.09.2014
comment
Гораздо более элегантное решение — переопределить метод DefaultStyleLookupName, чтобы он возвращал «ButtonStyle». - person Mike Sutton; 17.09.2014
comment
@Майк, я уверен, что ты прав. Не могли бы вы объяснить, почему это более элегантно, пожалуйста. - person David Heffernan; 17.09.2014
comment
@Майк, хорошо. Думаю, я понимаю, почему. - person David Heffernan; 17.09.2014