Flutter GUI构建插件objd_gui的使用

Flutter GUI构建插件objD Gui的使用

objD Gui 插件允许你通过定义一些属性来构建任何类型的GUI,无论是简单的还是非常复杂的。objD会处理其余的工作。

这个插件还有一个网页界面:https://stevertus.com/tools/gui

你可以在这里阅读如何使用它:https://stevertus.com/article/guiguide

安装

安装插件很简单,只需要在现有的 objD 项目中添加 objd_gui 作为依赖项到 pubspec.yaml 文件中。

dependencies:
  objd_gui: 0.1.2

然后导入该包:

import 'package:objd_gui/gui.dart';

GuiModule

包的核心部分是 GuiModule。你可以在 packmodules 列表中使用它,或者像通常的 widget 一样包含在某个位置,以便根据条件运行。

每个容器类型和大小都有一个构造函数:GuiModule.chest, GuiModule.dropper, GuiModule.hopper, GuiModule.enderchest, GuiModule.inventory, GuiModule.minecartGuiModule.item

Pack(
  ...,
  main: ..., // 必须包含!
  load: ...
  modules: [
    GuiModule.chest(
      Location('-49 56 -36'),
      ...
    )
  ]
)

除了 GuiModule.item 外,它们的工作方式大致相同,只是代表不同的GUI大小。例如,如果你有一个9x3的容器(如桶),则会使用 chest 构造函数。objD 不会放置任何方块或召唤实体,这些必须由你自己管理。

根据容器,GuiModule 还需要容器的 Location、要检查的 Entity 或必须选择以显示GUI的 Item

GuiPages

你的GUI可以分为多个页面。这些页面可以切换并显示不同的内容或具有不同的功能。因此,对于每个页面,整个GUI将重新构建。

GuiModule.chest(
  Location('-49 56 -36'),
  pages: [
    GuiPage(
      [
        ...
      ],
      fillEmptySlots: true,
      placeholder: Item(Items.gray_stained_glass_pane)
    )
  ]
)

每个页面都需要一个 GuiSlot 列表,应该放在当前GUI中。通过 fillEmptySlots 选项,你可以切换是否填充未指定的槽位,并用 placeholder 提供的页面自身或如果不可用则用 GuiModuleplaceholder 填充。

GuiSlot

数据类 GuiSlot 实际上定义了在哪里发生什么。一般来说,它们可以被定义为一个项目和槽位的对。 你给生成器指定一个槽位来放置一个物品。简单吧? 其实它有更多的可定制性。有多种 GuiSlot 类型执行不同的动作。

Placeholder

我们已经讨论过 Placeholder。这是一个简单的物品,阻止相应的槽位,不能取出,也没有主要的操作。放置的物品是由 Module 或当前 Page 指定的 placeholder。但是你可以通过指定一个可选的物品来覆盖它。

GuiPage(
  [
    Placeholder(
      slot: Slot.chest(2,1),
      item: Item(Items.black_stained_glass_pane), // 覆盖那个难看的灰色
    )
  ],
)

EmptySlot

EmptySlot 只是确保指定的槽位不被填充或清除,所以用户可以将物品放入其中(这仅在你使用 fillEmptySlots 时才必要)。

EmptySlot(
  slot: Slot.chest(2,2),
)

Interactive

这种类型你可以做几乎任何事情。它的核心是一个可点击的物品。你可以选择性地指定一组 Widgets(操作)在点击物品时运行。此外,你还可以给它一个 countScore 来修改物品的数量(非常适合选项GUI、滑块、显示数据等)。这里需要指定物品。

Interactive(
  Item(Items.stone),
  slot: Slot.chest(2,5),
  actions: [
    Log('clicked stone'),
  ],
  countScore: Score(Entity.Player(), 'custom_score'),
)

ChangePage

最后一种类型是 ChangePage。顾名思义,这是一种简单的导航到不同页面的方式。如往常一样,你定义一个物品和槽位,以及要导航到的页面的索引(从1开始)。

ChangePage(
  2,
  Item(Items.arrow),
  slot: Slot.chest(3,9),
)

为了更方便地前后导航,你也可以使用 ChangePage.nextChangePage.prev:

ChangePage.next(
  Item(Items.arrow),
  slot: Slot.chest(3,9),
)
ChangePage.prev(
  Item(Items.arrow),
  slot: Slot.chest(3,1),
)

这个操作还会提前警告你,以防你想导航到不存在的页面。

动态填充GUI

到目前为止,我们总是将槽位与 GuiSlot 一起设置,并固定其位置。但是借助 objD 和生成的力量,你也可以留空槽位,让它找出第一个未被占用的槽位,并从左到右填充GUI。

如果我们定义另一个页面如下:

GuiPage(
  [
    ChangePage.prev(
      Item(Items.arrow),
    ),
    Interactive(
      Item(Items.apple),
      actions: [
        Log('MY Nice Apple'),
      ],
    ),
    EmptySlot(
      slot: Slot.chest(1,2),
    ),
  ],
  fillEmptySlots: true,
)

它会这样填充GUI:

GUI填充示例

注意,具有固定位置的 EmptySlot 在填充GUI时被跳过了。

将GUI集成到你的数据包中

到现在为止,我们只学会了如何构建多个页面,与物品交互,并用占位符填充其余部分。但所有这些都是一直在一个静态的箱子中,在一个位置上。如何自定义并将其与你的数据包结合使用? 答案很简单。GuiModule 是一个Widget。这意味着你可以在任何地方使用它,而不仅仅是在模块中。

让我们说我们想将GUI应用到所有标记了区域效果云的位置的箱子。

在主文件中,我们可以这样包含我们的模块:

File(
  'main',
  child: Execute.at(
    Entity(type: Entities.area_effect_cloud, tags: ['custom_gui_location']),
    children: [
      GuiModule.chest(
        Location.here(),
        ...
      )
    ]
  )
)

这确保了GUI的代码在所有AEC活跃的位置运行。

为了进一步修改内部逻辑并将GUI集成到你的数据包中,你还可以更改使用的记分板。该模块只使用1-2个记分板,两者都基于玩家。

GuiModule.chest(
  ...,
  countScore: 'my_count',
  pageScore: 'my_page',
)

countScore 用于检查GUI中的物品是否已更改(如果有物品被点击)。它通过计算所有物品并与之前进行比较来实现。

pageScore 保存当前页面(索引)的状态。你也可以编程改变这个分数来改变GUI页面。

GlobalSlots

通过模块上的 globalSlots 属性,你可以轻松定义一次出现于每个页面上的槽位(例如子菜单、分页)。

让我们用导航箭头来做这个:

GuiModule.chest(
  ...,
  globalSlots: [
    ChangePage.prev(
      Item(Items.arrow),
      slot: Slot.chest(3,1),
    ),
    ChangePage.next(
      Item(Items.arrow),
      slot: Slot.chest(3,9),
    )
  ]
)

完整示例

到目前为止,我们构建了一个具有两个页面的GUI,能够在这之间导航,触发操作,并动态设置槽位。

完整的示例代码如下:

import 'package:objd/core.dart';
import 'package:objd_gui/gui.dart';

void main(List<String> args) {
  createProject(
    Project(
      name: 'gui_test',
      version: 17,
      generate: Pack(
        name: 'gui',
        load: File('load'), // 重要!加载记分板
        main: File(
          'main',
          child: Execute.at(
            Entity(
              type: Entities.armor_stand,
              tags: ['custom_gui_location'],
            ),
            children: [
              GuiModule.chest(
                Location.here(),
                pages: [
                  GuiPage(
                    [
                      Placeholder(
                        slot: Slot.chest(2, 1),
                        item: Item(
                          Items.black_stained_glass_pane,
                        ), // 覆盖那个难看的灰色
                      ),
                      EmptySlot(
                        slot: Slot.chest(2, 2),
                      ),
                      Interactive(
                        Item(Items.stone),
                        slot: Slot.chest(2, 5),
                        actions: [
                          Log('clicked stone'),
                        ],
                        countScore: Score(Entity.Player(), 'custom_score'),
                      ),
                      ChangePage(
                        2,
                        Item(Items.arrow),
                        slot: Slot.chest(3, 9),
                      ),
                    ],
                    fillEmptySlots: true,
                    placeholder: Item(Items.gray_stained_glass_pane),
                  ),
                  GuiPage(
                    [
                      Interactive(
                        Item(Items.apple),
                        actions: [
                          Log('MY Nice Apple'),
                        ],
                      ),
                      EmptySlot(
                        slot: Slot.chest(1, 2),
                      ),
                    ],
                    fillEmptySlots: true,
                  ),
                ],
                placeholder: Item(Items.light_gray_stained_glass_pane),
                globalSlots: [
                  ChangePage.prev(
                    Item(Items.arrow),
                    slot: Slot.chest(3, 1),
                  ),
                  ChangePage.next(
                    Item(Items.arrow),
                    slot: Slot.chest(3, 9),
                  ),
                ],
                countScore: 'my_count',
                pageScore: 'my_page',
                path: 'my_gui',
              )
            ],
          ),
        ),
        modules: [
          // 或者在这里
        ],
      ),
    ),
  );
}

绑定GUI到一个物品

objd_gui 还包括一个特性,即如果玩家手持特定物品,则显示和隐藏GUI(作为矿车)。因此,这有点像游戏菜单或便携式菜单。因此,可以指定一些额外的参数。

GuiModule.item(
  Item(Items.stone),
  alwaysActive: false,
  name: TextComponent('my awesome gui'),
)

更多关于Flutter GUI构建插件objd_gui的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter GUI构建插件objd_gui的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


objd_gui 是一个用于 Flutter 的插件,旨在简化 GUI(图形用户界面)的构建过程。它提供了一种声明式的方式来构建和管理 GUI 元素,使得开发者可以更高效地创建复杂的用户界面。以下是如何使用 objd_gui 插件的基本步骤和示例。

1. 安装插件

首先,你需要在 pubspec.yaml 文件中添加 objd_gui 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  objd_gui: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装依赖。

2. 导入插件

在你的 Dart 文件中导入 objd_gui 插件:

import 'package:objd_gui/objd_gui.dart';

3. 使用 objd_gui 构建 GUI

objd_gui 提供了一系列的 Widget 和工具来帮助你构建 GUI。以下是一个简单的示例,展示如何使用 objd_gui 创建一个基本的界面。

import 'package:flutter/material.dart';
import 'package:objd_gui/objd_gui.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: GuiScreen(),
    );
  }
}

class GuiScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('objd_gui Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            GuiButton(
              onPressed: () {
                print('Button Pressed!');
              },
              child: Text('Press Me'),
            ),
            SizedBox(height: 20),
            GuiTextField(
              hintText: 'Enter something...',
              onChanged: (value) {
                print('Text changed: $value');
              },
            ),
          ],
        ),
      ),
    );
  }
}

4. 解释代码

  • GuiButton: 这是一个自定义的按钮部件,它封装了 Material Design 的 ElevatedButton,并提供了更简单的 API 来处理按钮点击事件。

  • GuiTextField: 这是一个自定义的文本输入部件,它封装了 Material Design 的 TextField,并提供了更简单的 API 来处理文本输入变化。

5. 自定义和扩展

objd_gui 提供了基础的部件,但你可以根据需要自定义和扩展这些部件。例如,你可以创建自己的 GuiCardGuiDialog 部件,以更好地适应你的应用需求。

6. 运行应用

完成上述步骤后,你可以运行你的 Flutter 应用,并查看 objd_gui 插件的效果。

flutter run
回到顶部