Erstellen einer 2D-Benutzeroberfläche in einer 3D-Anwendung (FireMonkey 3D-Tutorial)
Nach oben zu Tutorial: Erstellen einer FireMonkey 3D-Anwendung
In einer 3D-Anwendung können 2D-Komponenten, wie Schaltflächen oder Listen, nicht direkt verwendet werden. Wenn eine 2D-Komponente in einem 3D-Container abgelegt wird, wird die Komponente nicht gerendert, sondern in der Strukturansicht als untergeordnetes Steuerelement angezeigt. Es gibt aber eine einfache Möglichkeit, mit diesem Problem umzugehen, nämlich durch Erstellen einer Brücke zwischen den 3D- und den 2D-Szenen. FireMonkey stellt dafür die Komponente FMX.Layers3D.TLayer3D bereit.
Inhaltsverzeichnis
Hinzufügen und Anpassen einer 2D-Oberfläche (TLayer3D) und einer Schaltfläche (TButton)
- Wählen Sie das Formular aus dem vorhergehenden Tutorial im Objektinspektor oder in der Strukturansicht aus, und doppelklicken Sie in der Tool-Palette auf TLayer3D.
- Jetzt können Sie die TLayer3D-Komponente als Oberfläche für FireMonkey-2D-Komponenten verwenden.
- Wählen Sie in der Strukturansicht oder dem Objektinspektor die Komponente TLayer3D aus, und fügen Sie eine TButton-Komponente hinzu. Stellen Sie in der Strukturansicht sicher, dass die Schaltfläche der TLayer3D-Komponente und nicht dem Formular untergeordnet ist (wenn Sie die Hierarchie korrigieren müssen, ziehen Sie TButton auf TLayer3D).
- Ändern Sie den Projection-Typ der TLayer3D-Komponente, um eine 2D-Oberfläche zu simulieren. Legen Sie im Objektinspektor die folgenden Eigenschaften für die TLayer3D-Komponente fest:
- Projection = Screen
- Eine Bildschirmprojektion ist eine pixelweise Projektion auf die Bildschirmebene mit einer festen (unsichtbaren) Kamera, und die vordere Ebene des 3D-Pyramidenstumpfs ist jetzt eine Bildschirmebene. Jedes Objekt ist weiterhin 3D, kann aber wie 2D bearbeitet werden.
- Ihre 3D-Anwendung sollte jetzt so wie in der folgenden Abbildung dargestellt aussehen:
- Wie Sie sehen, verdeckt die TLayer3D-Komponente die Szene fast vollständig. Setzen Sie im Objektinspektor folgende Eigenschaften für TLayer3D:
- Align auf
MostRight
(oder eine beliebige andere Ausrichtung) - Width auf
150
(oder eine andere Breite in Pixel)
- Align auf
Hinzufügen und Anordnen von 2D-Komponenten
Löschen Sie nun die hinzugefügten Schaltflächen, damit Sie andere Schaltflächen hinzufügen können, mit denen die 3D-Objekte auf dem Formular gedreht und verschoben werden oder deren Größe geändert wird.
- Setzen Sie den Fokus auf TLayer3D, und fügen Sie fünf TGroupBox-Steuerelemente hinzu.
- Markieren Sie in der Strukturansicht alle Gruppenfelder, indem Sie die Taste STRG gedrückt halten und mit der Maus auf jedes Gruppenfeld klicken. Setzen Sie im Objektinspektor die Eigenschaft Align auf
Top
. - Wählen Sie die obersten drei Gruppenfelder aus, und setzen Sie im Objektinspektor die Eigenschaft Height auf
70
(oder einen anderen Wert, der Ihnen für das endgültige Layout besser gefällt). - Wählen Sie jedes TGroupBox-Steuerelement aus, und setzen Sie:
- Text auf Width, Height, Depth, Move und Rotate
- Name auf WidthGroupBox, HeightGroupBox, DepthGroupBox, MoveGroupBox und RotateGroupBox. Stellen Sie sicher, dass Sie die Einträge für Name und Text sich jeweils entsprechen (Width und WidthGroupBox, Height und HeightGroupBox usw.)
- Die Eigenschaft Enabled auf False.
- Fügen Sie den ersten drei TGroupBox-Steuerelementen Paare von jeweils zwei Schaltflächen hinzu. Einer Schaltfläche wird zum Vergrößern und eine zum Verkleinern der Breite, Höhe und Tiefe verwendet.
- Ändern Sie die Namen der Schaltflächenpaare wie folgt:
- IncreaseWidthButton und DecreaseWidthButton
- IncreaseHeightButton und DecreaseHeightButton
- IncreaseDepthButton und DecreaseDepthButton
- Ändern Sie die Eigenschaft Text entsprechend den Schaltflächennamen.
- Fügen Sie dem Gruppenfeld Move drei Schaltflächenpaare hinzu.
- Ändern Sie die Namen der Schaltflächenpaare wie folgt:
- MoveRightButton und MoveLeftButton
- MoveDownButton und MoveUpButton
- MoveBackButton und MoveFrontButton
- Ändern Sie die Eigenschaft Text entsprechend den Schaltflächennamen.
- Fügen Sie dem Gruppenfeld Rotate drei TTrackBar-Komponenten hinzu, mit denen das 3D-Objekt um jede Achse gedreht wird.
- Ändern Sie die Namen der TTrackBar-Steuerelemente in RotateXTrackBar, RotateYTrackBar und RotateZTrackBar.
- Setzen Sie im Objektinspektor die Eigenschaft Min jedes Schiebereglers auf
-360
und die Eigenschaft Max auf360
.
- Markieren Sie in der Strukturansicht alle Gruppenfelder, indem Sie die Taste STRG gedrückt halten und mit der Maus auf jedes Gruppenfeld klicken. Setzen Sie im Objektinspektor die Eigenschaft Align auf
- Fügen Sie dem Formular eine weitere TLayer3D-Komponente hinzu.
- Setzen Sie im Objektinspektor die Eigenschaft Projection der neuen TLayer3D-Komponente auf
Screen
und die Eigenschaft Align aufTop
. - Fügen Sie der neuen TLayer3D-Komponente zwei TGroupBox-Steuerelemente hinzu.
- Wählen Sie jedes TGroupBox-Steuerelement aus, und setzen Sie:
- Fügen Sie ManipulateItemGroupBox drei TRadioButton-Steuerelemente hinzu, eins für jedes 3D-Objekt in der Szene.
- Wählen Sie jedes TRadioButton-Steuerelement aus, und setzen Sie:
- Fügen Sie LightGroupBox ein TButton-Steuerelement hinzu.
- Wählen Sie die Schaltfläche aus, und setzen Sie:
- Setzen Sie im Objektinspektor die Eigenschaft Projection der neuen TLayer3D-Komponente auf
Das endgültige Layout sollte wie folgt aussehen:
Hinzufügen von Ereignissen und Ereignisbehandlungsroutinen
Die Anwendung besteht jetzt aus einer einfachen 3D-Szene, in der Sie Objekten Ereignisse hinzufügen können.
- 1. Um das zu bearbeitende 3D-Objekt festzulegen, deklarieren Sie eine globale String-Variable zur Aufnahme des Objektnamens.
Im Ereignis OnChange des Schiebereglers kann das Objekt mit dem Fokus gedreht werden. Um zu vermeiden, dass die Drehwinkel des vorherigen Objekts aktualisiert werden, wenn ein anderes Objekt ausgewählt wird, fügen Sie die boolesche Variable RotateFlag hinzu. Wenn diese Variable auf False gesetzt ist, wird der Code in der Ereignisbehandlungsroutine OnChange nicht ausgelöst.
//Delphi declaration
var
Form1: TForm1;
ManipulatedItem: String;
RotateFlag: boolean;
// C++ declaration
TForm3D1 *Form3D1;
System::UnicodeString ManipulatedItem;
bool RotateFlag;
- 2. Fügen Sie den Optionsfeldern OnChange-Ereignisbehandlungsroutinen hinzu, indem Sie auf jedes Optionsfeld doppelklicken. Im Folgenden finden Sie den Delphi- und C++-Code für Cube1RadioButton. Der Code für Cube2RadioButton ist bis auf den Namen (Cube2 anstatt von Cube1) identisch.
// The Delphi implementation for the radio button OnChange event
procedure TForm1.Cube1RadioButtonChange(Sender: TObject);
begin
//enables the group boxes to manipulate Cube1
WidthGroupBox.Enabled := True;
HeightGroupBox.Enabled := True;
DepthGroupBox.Enabled := True;
MoveGroupBox.Enabled := True;
RotateGroupBox.Enabled := True;
//updates the values for the track bars to display the current value of the Cube1.RotationAngle
RotateFlag:=false;
RotateXTrackBar.Value := Cube1.RotationAngle.X;
RotateYTrackBar.Value := Cube1.RotationAngle.Y;
RotateZTrackBar.Value := Cube1.RotationAngle.Z;
RotateFlag:=True;
//Saves the name of the 3D object to be manipulated
ManipulatedItem:=Cube1.Name;
end;
// The C++ implementation for the radio button OnChange event
void __fastcall TForm3D1::Cube1RadioButtonChange(TObject *Sender)
{
//enables the group boxes to manipulate Cube1
WidthGroupBox->Enabled = true;
HeightGroupBox->Enabled = true;
DepthGroupBox->Enabled = true;
MoveGroupBox->Enabled = true;
RotateGroupBox->Enabled = true;
//updates the values for the track bars to display the current value of the Cube1.RotationAngle
RotateFlag = false;
RotateXTrackBar->Value = Cube1->RotationAngle->X;
RotateYTrackBar->Value = Cube1->RotationAngle->Y;
RotateZTrackBar->Value = Cube1->RotationAngle->Z;
RotateFlag = true;
//Saves the name of the 3D object to be manipulated
ManipulatedItem = Cube1->Name;
}
Bei LightRadioButton aktiviert der Code nicht alle Berabeitungsgruppenfelder. Das Verschieben und Ändern der Größe hat für TLight keine visuellen Effekte in der Szene. Die Implementierung von LightRadioButton lautet:
// The Delphi implementation for the radio button OnChange event
procedure TForm1.LightRadioButtonChange(Sender: TObject);
begin
//disables the group boxes that move and resize the light
WidthGroupBox.Enabled := False;
HeightGroupBox.Enabled := False;
DepthGroupBox.Enabled := False;
MoveGroupBox.Enabled := False;
// the light is manipulated only if it is on
if(Light1.Enabled=True) then
begin
RotateGroupBox.Enabled := True;
//updates the values for the track bars to display the current value of the Light1.RotationAngle
RotateFlag:=false;
RotateXTrackBar.Value := Light1.RotationAngle.X;
RotateYTrackBar.Value := Light1.RotationAngle.Y;
RotateZTrackBar.Value := Light1.RotationAngle.Z;
RotateFlag:=True;
//saves the name of the 3D object to be manipulated
ManipulatedItem:=Cube1.Name;
end
else
RotateGroupBox.Enabled := false;
end;
end;
// The C++ implementation for the radio button OnChange event
void __fastcall TForm3D1::LightRadioButtonChange(TObject *Sender)
{
//disables the group boxes that move and resize the light
WidthGroupBox->Enabled = false;
HeightGroupBox->Enabled = false;
DepthGroupBox->Enabled = false;
MoveGroupBox->Enabled = false;
// the light is manipulated only if it is on
if (Light1->Enabled == true)
{
RotateGroupBox->Enabled = true;
//updates the values for the track bars to display the current value of the Light1.RotationAngle
RotateFlag = false;
RotateXTrackBar->Value = Light1->RotationAngle->X;
RotateYTrackBar->Value = Light1->RotationAngle->Y;
RotateZTrackBar->Value = Light1->RotationAngle->Z;
RotateFlag = true;
//saves the name of the 3D object to be manipulated
ManipulatedItem=Cube1->Name;
}
else
RotateGroupBox->Enabled = false;
}
- 3. Implementierung der LightOnOffButton-Schaltfläche:
procedure TForm1.LightOnOffButtonClick(Sender: TObject);
begin
if Light1.Enabled = True then
begin
Light1.Enabled := False;
LightOnOffButton.Text := 'ON';
if(LightRadioButton.IsChecked) then
RotateGroupBox.Enabled:=False;
end
else
begin
Light1.Enabled := True;
LightOnOffButton.Text := 'OFF';
if(LightRadioButton.IsChecked) then
RotateGroupBox.Enabled:=True;
end;
end;
void __fastcall TForm3D1::LightOnOffButtonClick(TObject *Sender)
{
if (Light1->Enabled == true)
{
Light1->Enabled = false;
LightOnOffButton->Text = "ON";
if (LightRadioButton->IsChecked)
RotateGroupBox->Enabled = false;
}
else
{
Light1->Enabled = true;
LightOnOffButton->Text = "OFF";
if (LightRadioButton->IsChecked)
RotateGroupBox->Enabled = true;
}
}
Unterschiede zwischen "Licht an" und "Licht aus":
- 4. Die Implementierungen für die Schaltflächen zur Größenänderung sind ähnlich. Im Folgenden finden Sie die Implementierung für das Vergrößern und Verkleinern der Breite des 3D-Objekts.
//Increasing and decreasing the Width of the 3D object
procedure TForm1.IncreaseWidthButtonClick(Sender: TObject);
begin
TControl3D(FindComponent(ManipulatedItem)).Width:=TControl3D(FindComponent(ManipulatedItem)).Width+1;
end;
procedure TForm1.DecreaseWidthButtonClick(Sender: TObject);
begin
TControl3D(FindComponent(ManipulatedItem)).Width:=TControl3D(FindComponent(ManipulatedItem)).Width-1;
end;
void __fastcall TForm3D1::IncreaseWidthButtonClick(TObject *Sender)
{
((TControl3D*)(FindComponent(ManipulatedItem)))->Width=((TControl3D*)(FindComponent(ManipulatedItem)))->Width+1;
}
void __fastcall TForm3D1::DecreaseWidthButtonClick(TObject *Sender)
{
((TControl3D*)(FindComponent(ManipulatedItem)))->Width=((TControl3D*)(FindComponent(ManipulatedItem)))->Width-1;
}
- 5. Die Implementierungen für die Schaltflächen zum Verschieben sind ähnlich. Im Folgenden finden Sie die Implementierung für das Verschieben des 3D-Objekts nach rechts und links.
procedure TForm1.MoveRightButtonClick(Sender: TObject);
begin
TControl3D(FindComponent(ManipulatedItem)).Position.X:=TControl3D(FindComponent(ManipulatedItem)).Position.X+1;
end;
procedure TForm1.MoveLeftButtonClick(Sender: TObject);
begin
TControl3D(FindComponent(ManipulatedItem)).Position.X:=TControl3D(FindComponent(ManipulatedItem)).Position.X-1;
end;
void __fastcall TForm3D1::MoveRightButtonClick(TObject *Sender)
{
((TControl3D*)(FindComponent(ManipulatedItem)))->Position->X=((TControl3D*)(FindComponent(ManipulatedItem)))->Position->X+1;
}
void __fastcall TForm3D1::MoveLeftButtonClick(TObject *Sender)
{
((TControl3D*)(FindComponent(ManipulatedItem)))->Position->X=((TControl3D*)(FindComponent(ManipulatedItem)))->Position->X-1;
}
procedure TForm1.RotateXTrackBarChange(Sender: TObject);
begin
if (ManipulatedItem<>'') and (RotateFlag=True) then
TControl3D(FindComponent(ManipulatedItem)).RotationAngle.X:= RotateXTrackBar.Value;
end;
void __fastcall TForm3D1::RotateXTrackBarChange(TObject *Sender)
{
if (ManipulatedItem!="" && RotateFlag==true)
((TControl3D*)(FindComponent(ManipulatedItem)))->RotationAngle->X=RotateXTrackBar->Value;
}
- 7. Führen Sie das Projekt durch Drücken von F9 aus.
- Markieren Sie Cube1Radiobutton. Wenn Sie auf die Schaltflächen Increase/Decrease klicken, wird die Größe des Würfels geändert.
- Markieren Sie Cube1Radiobutton. Wenn Sie auf die Schaltflächen Left/Right klicken, ändert sich die Position des Würfels.
- Markieren Sie Cube1Radiobutton. Wenn Sie den Wert der Schieberegler erhöhen, wird der Würfel im Uhrzeigersinn gedreht, und wenn Sie den Wert verringern, wird der Würfel gegen den Uhrzeigersinn gedreht.
- Markieren Sie LightRadiobutton. Wenn Sie den Wert der Schieberegler erhöhen, wird das Licht gedreht und der Effekt auf Cube2 sichtbar.
Zurück
Siehe auch
- Erstellen einer FireMonkey-Komponente (Delphi)
- Erstellen einer FireMonkey-Komponente (C++)
- Geräteübergreifende 3D-Anwendung
- Ereignisse und Ereignisbehandlungsroutinen verwenden
Beispiele
- FireMonkey 3D Arrows (Beispiel)
- FireMonkey First App3D (Beispiel)
- FireMonkey GUI3d (Beispiel)
- FireMonkey Cameras Textures 3D (Beispiel)