用 XML 和 Java 构建树莓派打印机的用户界面
嵌入式 用户界面

> 
> 使用 TotalCross 来快速构建嵌入式系统程序的用户界面。
> 
> 
> 


![](/data/attachment/album/202205/21/110711zv3t7n1o7hllhodt.jpg "Tips and gears turning")


从头开始构建 GUI 是一个非常耗时的过程，以硬编码的方式处理所有的位置和对齐对于一些程序员来说确实很困难。所以在本文中，我将演示如何使用 XML 加快这一过程。


本项目使用 [TotalCross](https://opensource.com/article/20/7/totalcross-cross-platform-development) 作为目标框架。TotalCross 是一个开源的跨平台软件开发工具包（SDK），旨在更快地为嵌入式设备创建 GUI。TotalCross 无需在设备上运行 Java 即可提供 Java 的开发优势，因为它使用自己的字节码和虚拟机（<ruby> TC 字节码 <rt>  TC bytecode </rt></ruby> 和 TCVM）来增强性能。


我还使用了 Knowcode-XML，这是一个用于 TotalCross 框架的开源 XML 解析器，它可以将 XML 文件转换为 TotalCross 组件。


### 项目需求


要重现此项目，你需要：


* [KnowCode-XML](https://github.com/TotalCross/knowcode-xml)
* [VSCode](https://code.visualstudio.com/) 或 [VSCodium](https://opensource.com/article/20/6/open-source-alternatives-vs-code)
* [一个 Android 开发环境](https://developer.android.com/studio)
* [用于 VSCode 的 TotalCross 插件](https://marketplace.visualstudio.com/items?itemName=totalcross.vscode-totalcross)
* 适用于你的开发平台（[Linux](https://opensource.com/article/19/11/install-java-linux)、[Mac](https://opensource.com/article/20/7/install-java-mac) 或 [Windows](http://adoptopenjdk.net)）的 Java，需要 Java 11（或更高版本）
* [Git](https://opensource.com/life/16/7/stumbling-git)


### 制作嵌入式应用程序


该应用程序由一个具有扫描、打印和复印等基本打印功能的嵌入式 GUI 组成。


![打印机初始化画面](/data/attachment/album/202205/21/110714mpcujqtoju8lbo31.png "printer init screen")


构建这个 GUI 需要几个步骤，包括使用 Android-XML 生成 GUI，然后使用 Knowcode-XML 解析器在 TotalCross 框架上运行它。


#### 1、生成 Android XML


要创建 XML 文件，首先构建一个简单的 Android 屏幕，然后对其进行自定义。如果你不知道如何编写 Android-XML，或者你只是想简单尝试一下，你可以从这个 [GitHub 项目](https://github.com/TotalCross/embedded-samples/tree/main/printer-application/src/main/resources/layout) 中下载这个应用程序的 XML。该项目还包含渲染 GUI 要用到的图片。


#### 2、调整 XML


生成 XML 文件后，你需要进行一些微调以确保所有内容都已经对齐、比例正确并且图像的路径正确。


将 XML 布局添加到 `Layouts` 文件夹，将所有资源添加到 `Drawable` 文件夹。然后你就可以开始自定义 XML 了。


例如，如果想要更改 XML 对象的背景，可以更改 `android:background` 属性：



```
android:background="@drawable/scan"

```

你也可以使用 `tools:layout_editor_absoluteX` 和 `tools:layout_editor_absoluteY` 更改对象的位置：



```
tools:layout_editor_absoluteX="830dp"
tools:layout_editor_absoluteY="511dp"

```

或者使用 `android:layout_width` 和 `android:layout_height` 更改对象的大小：



```
android:layout_width="70dp"
android:layout_height="70dp"

```

如果要在对象上放置文本，可以使用 `android:textSize`、`android:text`、`android:textStyle` 和 `android:textColor`：



```
android:textStyle="bold"
android:textColor="#000000"
android:textSize="20dp"
android:text="2:45PM"

```

下面是一个完整的 XML 对象的示例：



```
    <ImageButton
           android:id="@+id/ImageButton"
           android:layout_width="70dp"
           android:layout_height="70dp"
           tools:layout_editor_absoluteX="830dp"
           tools:layout_editor_absoluteY="511dp"
           android:background="@drawable/home_config" />

```

#### 3、在 TotalCross 上运行 GUI


完成所有 XML 调整后，就可以在 TotalCross 上运行它了。在 TotalCross 扩展（LCTT 译注：在 VSCode 里面）上创建一个新项目，并将 `XML` 和 `Drawable` 文件夹添加到 `Main` 文件夹里。如果你仍然不确定如何创建 TotalCross 项目，请参阅我们的 [入门指南](https://totalcross.com/get-started/?utm_source=opensource&utm_medium=article&utm_campaign=printer)。


配置好环境后，使用 `totalcross.knowcode.parse.XmlContainerFactory` 和 `import totalcross.knowcode.parse.XmlContainerLayout` 在 TotalCross 框架上使用 XML GUI。 你可以在其 [GitHub 页面](https://github.com/TotalCross/knowcode-xml) 上找到更多关于使用 KnowCode-XML 的信息。


#### 4、添加过渡效果


这个项目的平滑过渡效果是由 `SlidingNavigator` 类创建的，它使用 TotalCross 的 `ControlAnimation` 类从一个屏幕滑到另一个屏幕。


在 `XMLpresenter` 类上调用 `SlidingNavigator`：



```
new SlidingNavigator(this).present(HomePresenter.class);

```

在 `SlidingNavigator` 类上实现 `present` 函数：



```
public void present(Class<? extends XMLPresenter> presenterClass)
         throws InstantiationException, IllegalAccessException {
      final XMLPresenter presenter = cache.containsKey(presenterClass) ? cache.get(presenterClass)
            : presenterClass.newInstance();
      if (!cache.containsKey(presenterClass)) {
         cache.put(presenterClass, presenter);
      }

      if (presenters.isEmpty()) {
         window.add(presenter.content, LEFT, TOP, FILL, FILL);
      } else {
         XMLPresenter previous = presenters.lastElement();

         window.add(presenter.content, AFTER, TOP, SCREENSIZE, SCREENSIZE, previous.content);

```

使用动画控件中的 `PathAnimation` 来创建从一个屏幕到另一个屏幕的滑动动画：



```
         PathAnimation.create(previous.content, -Settings.screenWidth, 0, new ControlAnimation.AnimationFinished() {
            @Override
            public void onAnimationFinished(ControlAnimation anim) {
               window.remove(previous.content);
            }
         }, 1000).with(PathAnimation.create(presenter.content, 0, 0, new ControlAnimation.AnimationFinished() {
            @Override
            public void onAnimation Finished(Control Animation anim) {
               presenter.content.setRect(LEFT, TOP, FILL, FILL);
            }
         }, 1000)).start();
      }
      presenter.setNavigator(this);
      presenters.push(presenter);
      presenter.bind2();
      if (presenter.isFirstPresent) {
         presenter.onPresent();
         presenter.isFirstPresent = false;
      }

```

#### 5、加载环形进度条


打印机应用程序的另一个不错的功能是显示进度的加载屏幕动画。它包括文本和旋转动画。


![加载环形进度条](/data/attachment/album/202205/21/110714hkiski2ksyx2iw5s.png "Loading Spinner")


通过添加定时器和定时器监听器来更新进度标签，然后调用函数 `spinner.start()` 来实现此功能。所有的动画都是由 TotalCross 和 KnowCode 自动生成的：



```
public void startSpinner() {
        time = content.addTimer(500);
        content.addTimerListener((e) -> {
            try {
                progress(); // Updates the Label
            } catch (InstantiationException | IllegalAccessException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        });
        Spinner spinner = (Spinner) ((XmlContainerLayout) content).getControlByID("@+id/spinner");
        spinner.start();
    }

```

这里的环形进度条被实例化为对 XML 文件中描述的 `XmlContainerLayout` `spinner` 的引用：



```
<ProgressBar
android:id="@+id/spinner"
android:layout_width="362dp"
android:layout_height="358dp"
tools:layout_editor_absoluteX="296dp"
tools:layout_editor_absoluteY="198dp"
   android:indeterminateTint="#2B05C7"
style="?android:attr/progressBarStyle" />

```

#### 6、构建应用程序


是时候构建应用程序了。你可以在 `pom.xml` 中查看和更改<ruby> 目标系统 <rt>  target systems </rt></ruby>。 请确保 `Linux Arm` 目标可用。


如果你使用的是 VSCode，请按下键盘上的 `F1` 键，选择 `TotalCross: Package` 并等待完成。 然后就可以在 `Target` 文件夹中看到安装文件了。


#### 7、在树莓派上部署和运行应用程序


要使用 SSH 协议在 [树莓派](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/) 上部署应用程序，请按键盘上的 `F1`。选择 `TotalCross: Deploy&Run` 并提供有关你的 SSH 连接的信息，如：用户名、IP地址、密码和应用程序路径。


![TotalCross：部署与运行](/data/attachment/album/202205/21/110715hiug3itlwq34yyyy.png "TotalCross: Deploy&Run")


![配置 SSH 用户名](/data/attachment/album/202205/21/110715fr9p99wawpbwbzz7.png "SSH user")


![配置 IP 地址](/data/attachment/album/202205/21/110715e0u2jzzxnnthpzjv.png "IP address")


![输入密码](/data/attachment/album/202205/21/110715jhshrzwa17hpvkzx.png "Password")


![配置路径](/data/attachment/album/202205/21/110715vki6souu3eoxuvva.png "Path")


### 总结


KnowCode 让使用 Java 创建和管理应用程序屏幕变得更加容易。Knowcode-XML 将你的 XML 转换为 TotalCross GUI 界面，然后生成二进制文件以在你的树莓派上运行。


将 KnowCode 技术与 TotalCross 相结合，使你能够更快地创建嵌入式应用程序。 你可以访问我们在 GitHub 上的 [嵌入式示例](https://github.com/TotalCross/embedded-samples) 并编辑你自己的应用程序，了解你还可以做什么。


如果你有问题、需要帮助，或者只是想与其他嵌入式 GUI 开发人员互动，请随时加入我们的 [Telegram](https://t.me/totalcrosscommunity) 小组，讨论任何框架上的嵌入式应用程序。




---


via: <https://opensource.com/article/21/3/raspberry-pi-totalcross>


作者：[Edson Holanda Teixeira Junior](https://opensource.com/users/edsonhtj) 选题：[lujun9972](https://github.com/lujun9972) 译者：[CoWave-Fall](https://github.com/CoWave-Fall) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
Creating a GUI from scratch is a very time consuming process, dealing with all the positions and alignments in hard code can be really tough for some programmers. In this article, I demonstrate how to speed up this process using XML.

This project uses [TotalCross](https://opensource.com/article/20/7/totalcross-cross-platform-development) as the target framework. TotalCross is an open source, cross-platform software development kit (SDK) developed to create GUIs for embedded devices faster. TotalCross provides Java's development benefits without needing to run Java on a device because it uses its own bytecode and virtual machine (TC bytecode and TCVM) for performance enhancement.

I also use Knowcode-XML, an open source XML parser for the TotalCross framework, which converts XML files into TotalCross components.

## Project requirements

To reproduce this project, you need:

[KnowCode-XML](https://github.com/TotalCross/knowcode-xml)[VSCode](https://code.visualstudio.com/)[or VSCodium](https://opensource.com/article/20/6/open-source-alternatives-vs-code)[An Android development environment](https://developer.android.com/studio)[TotalCross plugin for VSCode](https://marketplace.visualstudio.com/items?itemName=totalcross.vscode-totalcross)- Java 11 or greater for your development platform (
[Linux](https://opensource.com/article/19/11/install-java-linux),[Mac](https://opensource.com/article/20/7/install-java-mac), or[Windows](http://adoptopenjdk.net)) [Git](https://opensource.com/life/16/7/stumbling-git)

## Building the embedded application

This application consists of an embedded GUI with basic print functionalities, such as scan, print, and copy.

![printer init screen printer init screen](https://opensource.com/sites/default/files/uploads/01_printergui.png)

(Edson Holanda Teixeira Jr, CC BY-SA 4.0)

Several steps are required to create this GUI, including generating the GUI with Android-XML and then using the Knowcode-XML parser to run it on the TotalCross Framework.

### 1. Generate the Android XML

For creating the XML file, first create a simple Android screen, and then customize it. If you don't know how to write Android-XM, or you just want a headstart, you can download this application’s XML from this [ GitHub project](https://github.com/TotalCross/embedded-samples/tree/main/printer-application/src/main/resources/layout). This project also contains the images you need to render the GUI.

### 2. Adjust the XML

After generating the XML files, you need to make some fine adjustments to make sure everything is aligned, with the right proportions, and has the correct path to the images.

Add the XML layouts to the **Layouts** folder and all the assets to the **Drawable** folder. Then you can start to customize the XML.

For example, if you want to change an XML object's background, change the `android:background`

attribute:

`android:background="@drawable/scan"`


You can change the object's position with `tools:layout_editor_absoluteX`

and `tools:layout_editor_absoluteY`

:

```
tools:layout_editor_absoluteX="830dp"
tools:layout_editor_absoluteY="511dp"
```


Change the object's size with `android:layout_width`

and `android:layout_height`

:

```
android:layout_width="70dp"
android:layout_height="70dp"
```


If you want to put text on an object, you can use `android:textSize`

, `android:text`

, `android:textStyle`

, and `android:textColor`

:

```
android:textStyle="bold"
android:textColor="#000000"
android:textSize="20dp"
android:text="2:45PM"
```


Here is an example of a complete XML object:

```
<ImageButton
android:id="@+id/ImageButton"
android:layout_width="70dp"
android:layout_height="70dp"
tools:layout_editor_absoluteX="830dp"
tools:layout_editor_absoluteY="511dp"
android:background="@drawable/home_config" />
```


### 3. Run the GUI on TotalCross


After you make all the XML adjustments, it's time to run it on TotalCross. Create a new project on the TotalCross extension and add the **XML** and **Drawable** folders to the **Main** folder. If you're not sure how to create a TotalCross project, see our [get started guide](https://totalcross.com/get-started/?utm_source=opensource&utm_medium=article&utm_campaign=printer).

After configuring the environment, use `totalcross.knowcode.parse.XmlContainerFactory`

and `import totalcross.knowcode.parse.XmlContainerLayout`

to use the XML GUI on the TotalCross framework. You can find more information about using KnowCode-XML on its [GitHub page](https://github.com/TotalCross/knowcode-xml).

### 4. Add transitions

This project's smooth transition effect is created by the `SlidingNavigator`

class, which uses TotalCross' `ControlAnimation`

class to slide from one screen to the other.

Call `SlidingNavigator`

on the `XMLpresenter`

class:

`new SlidingNavigator(this).present(HomePresenter.class);`


Implement the `present`

function on the `SlidingNavigator`

class:

```
public void present(Class<? extends XMLPresenter> presenterClass)
throws InstantiationException, IllegalAccessException {
final XMLPresenter presenter = cache.containsKey(presenterClass) ? cache.get(presenterClass)
: presenterClass.newInstance();
if (!cache.containsKey(presenterClass)) {
cache.put(presenterClass, presenter);
}
if (presenters.isEmpty()) {
window.add(presenter.content, LEFT, TOP, FILL, FILL);
} else {
XMLPresenter previous = presenters.lastElement();
window.add(presenter.content, AFTER, TOP, SCREENSIZE, SCREENSIZE, previous.content);
```


`PathAnimation`

in animation control creates the sliding animation from one screen to another:

```
PathAnimation.create(previous.content, -Settings.screenWidth, 0, new ControlAnimation.AnimationFinished() {
@Override
public void onAnimationFinished(ControlAnimation anim) {
window.remove(previous.content);
}
}, 1000).with(PathAnimation.create(presenter.content, 0, 0, new ControlAnimation.AnimationFinished() {
@Override
public void onAnimation Finished(Control Animation anim) {
presenter.content.setRect(LEFT, TOP, FILL, FILL);
}
}, 1000)).start();
}
presenter.setNavigator(this);
presenters.push(presenter);
presenter.bind2();
if (presenter.isFirstPresent) {
presenter.onPresent();
presenter.isFirstPresent = false;
}
```


### 5. Load spinners

Another nice feature in the printer application is the loading screen animation that shows progress. It includes text and a spinning animation.

![Loading Spinner Loading Spinner](https://opensource.com/sites/default/files/uploads/03progressspinner.png)

(Edson Holanda Teixeira Jr, CC BY-SA 4.0)

Implement this feature by adding a timer and a timer listener to update the progress label, then call the function `spinner.start()`

. All of the animations are auto-generated by TotalCross and KnowCode:

```
public void startSpinner() {
time = content.addTimer(500);
content.addTimerListener((e) -> {
try {
progress(); // Updates the Label
} catch (InstantiationException | IllegalAccessException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
});
Spinner spinner = (Spinner) ((XmlContainerLayout) content).getControlByID("@+id/spinner");
spinner.start();
}
```


The spinner is instantiated as a reference to the `XmlContainerLayout`

spinner described in the XML file:

```
<ProgressBar
android:id="@+id/spinner"
android:layout_width="362dp"
android:layout_height="358dp"
tools:layout_editor_absoluteX="296dp"
tools:layout_editor_absoluteY="198dp"
android:indeterminateTint="#2B05C7"
style="?android:attr/progressBarStyle" />
```


### 6. Build the application

It's time to build the application. You can see and change the target systems in `pom.xml`

. Make sure the **Linux Arm** target is available.

If you are using VSCode, press **F1** on the keyboard, select **TotalCross: Package** and wait for the package to finish. Then you can see the installation files in the **Target** folder.

### 7. Deploy and run the application on Raspberry Pi

To deploy the application on a [Raspberry Pi 4](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/) with the SSH protocol, press **F1** on the keyboard. Select **TotalCross: Deploy&Run** and provide information about your SSH connection: User, IP, Password, and Application Path.

![TotalCross: Deploy&Run TotalCross: Deploy&Run](https://opensource.com/sites/default/files/uploads/04_totalcross-deployrun.png)

(Edson Holanda Teixeira Jr, CC BY-SA 4.0)

![SSH user SSH user](https://opensource.com/sites/default/files/uploads/05_ssh.png)

(Edson Holanda Teixeira Jr, CC BY-SA 4.0)

![IP address IP address](https://opensource.com/sites/default/files/uploads/06_ip.png)

(Edson Holanda Teixeira Jr, CC BY-SA 4.0)

![Password Password](https://opensource.com/sites/default/files/uploads/07_password.png)

(Edson Holanda Teixeira Jr, CC BY-SA 4.0)

![Path Path](https://opensource.com/sites/default/files/uploads/08_path.png)

(Edson Holanda Teixeira Jr, CC BY-SA 4.0)

Here's what the application looks like running on the machine.

## What's next?

KnowCode makes it easier to create and manage your application screens using Java. Knowcode-XML translates your XML into a TotalCross GUI that in turn generates the binary to run on your Raspberry Pi.

Combining KnowCode technology with TotalCross enables you to create embedded applications faster. Find out what else you can do by accessing our [embedded samples](https://github.com/TotalCross/embedded-samples) on GitHub and editing your own application.

If you have questions, need help, or just want to interact with other embedded GUI developers, feel free to join our [Telegram](https://t.me/totalcrosscommunity) group to discuss embedded applications on any framework.

## 1 Comment