Android App开发-简单控件(4)——按钮触控和图像显示

3.4 按钮触控

本节介绍了按钮控件的常见用法,包括:如何设置大小写属性与点击属性,如何响应按钮的点击事件和长按事件,如何禁用按钮又该如何启用按钮,等等。

3.4.1 按钮控件Button

除了文本视图之外,按钮Button也是一种基础控件。因为Button是由TextView派生而来,所以文本视图拥有的属性和方法,包括文本内容、文本大小、文本颜色等,按钮控件均能使用。

不同的是,Button拥有默认的按钮背景,而TextView默认无背景;Button的内部文本默认居中对齐,而TextView的内部文本默认靠左对齐。此外,按钮还要额外注意textAllCaps与onClick两个属性,分别介绍如下:

1.textAllCaps属性

对于TextView来说,text属性设置了什么文本,文本视图就显示什么文本。但对于Button来说,不管text属性设置的是大写字母还是小写字母,按钮控件都默认转成大写字母显示。比如在XML文件中加入下面的Button标签:

  <Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="Hello World"/>

编译运行后的App界面,按钮上显示全大写的“HELLO WORLD”,而非原来大小写混合的“Hello World”。显然这个效果不符合预期,为此需要给Button标签补充textAllCaps属性,该属性默认为true表示全部转为大写,如果设置为false则表示不转为大写。于是在布局文件添加新的Button标签,该标签补充了android:textAllCaps=“false”,具体内容如下所示:

  <Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="Hello World"android:textAllCaps="false"/>

再次运行App,此时包含新旧按钮的界面如图所示,可见textAllCaps属性果然能够控制大小写转换。

在这里插入图片描述

2.onClick属性

按钮之所以成为按钮,是因为它会响应按下动作,就手机而言,按下动作等同于点击操作,即手指轻触屏幕然后马上松开。每当点击按钮之时,就表示用户确认了某个事项,接下来轮到App接着处理了。

onClick属性便用来接管用户的点击动作,该属性的值是个方法名,也就是当前页面的Java代码存在这么一个方法:当用户点击按钮时,就自动调用该方法。

譬如下面的Button标签指定了onClick属性值为doClick,表示点击该按钮会触发Java代码中的doClick方法:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".ButtonStyleActivity"><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="直接指定点击方法"android:textColor="@color/black"android:textSize="17sp"android:onClick="doClick"/><TextViewandroid:id="@+id/tv_result"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="这里查看点击结果"android:textColor="@color/black"android:textSize="17sp"/></LinearLayout>

与之相对应,页面所在的Java代码需要增加doClick方法,方法代码示例如下:

package com.example.buttoncontrols;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import com.example.buttoncontrols.util.DateUtil;public class ButtonStyleActivity extends AppCompatActivity {private TextView textView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_button_style);textView = findViewById(R.id.tv_result);}public void doClick(View view){String desc=String.format("%s 您点击了按钮:%s",DateUtil.getNowTime(),((Button)view).getText());textView.setText(desc);}
}

然后编译运行,并在App界面上点击新加的按钮,点击前后的界面如下面两张图所示。

在这里插入图片描述

点击之后效果图:

在这里插入图片描述

比较两张图的文字差异,可见点击按钮之后确实调用了doClick方法。

3.4.2 点击事件和长按事件

1. 点击事件

虽然按钮控件能够在XML文件中通过onClick属性指定点击方法,但是方法的名称可以随便叫,既能叫doClick也能叫doTouch,甚至叫它doA或doB都没问题,这样很不利于规范化代码,倘若以后换了别人接手,就不晓得doA或doB是干什么用的。因此在实际开发中,不推荐使用Button标签的onClick属性,而是在代码中给按钮对象注册点击监听器。

所谓监听器,意思是专门监听控件的动作行为,它平时无所事事,只有控件发生了指定的动作,监听器才会触发开关去执行对应的代码逻辑点击监听器需要实现接口View.OnClickListener,并重写onClick方法补充点击事件的处理代码,再由按钮调用setOnClickListener方法设置监听器对象。比如下面的代码给按钮控件btn_click_single设置了一个点击监听器:

// 定义一个点击监听器,它实现了接口View.OnClickListener
class MyOnClickListener implements View.OnClickListener {@Overridepublic void onClick(View v) { // 点击事件的处理方法String desc = String.format("%s 您点击了按钮:%s",DateUtil.getNowTime(), ((Button)v).getText());// 设置文本视图的文本内容tv_result.setText(desc); }
}

接着运行App,点击按钮之后的界面如图所示,可见点击动作的确触发了监听器的onClick方法

在这里插入图片描述

如果一个页面只有一个按钮,单独定义新的监听器倒也无妨,可是如果存在许多按钮,每个按钮都定义自己的监听器,那就劳民伤财了。对于同时监听多个按钮的情况,更好的办法是注册统一的监听器,也就是让当前页面实现接口View.OnClickListener,如此一来,onClick方法便写在了页面代码之内。因为是统一的监听器,所以onClick内部需要判断是哪个按钮被点击了,也就是利用视图对象的getId方法检查控件编号,完整的onClick代码举例如下:

 // 公共的点击事件监听@Overridepublic void onClick(View v) {if (v.getId()==R.id.btn_click_public){String desc=String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(),((Button) v).getText());tvResult.setText(desc);}}

当然该页面的onCreate内部别忘了调用按钮对象的setOnClickListener方法,把按钮的点击监听器设置成当前页面,设置代码如下所示:

// 从布局文件中获取名为btn_click_public的按钮控件
Button btn_click_public = findViewById(R.id.btn_click_public);
// 设置点击监听器,一旦用户点击按钮,就触发监听器的onClick方法
btn_click_public.setOnClickListener(this);

重新运行App,点击第二个按钮之后的界面如图所示,可见当前页面的onClick方法也正确执行了。

在这里插入图片描述

点击实践完整代码如下:

XML布局文件代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".ButtonClickActivity"><Buttonandroid:id="@+id/btn_click_single"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="指定单独的点击监听器"android:textColor="#000000"android:textSize="17sp"/><Buttonandroid:id="@+id/btn_click_public"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="指定公共的点击监听器"android:textColor="#000000"android:textSize="17sp"/><TextViewandroid:id="@+id/tv_result"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="5dp"android:textColor="@color/black"android:textSize="17sp"android:text="这里查看按钮点击的结果"/>
</LinearLayout>

Java 逻辑代码如下:

package com.example.buttoncontrols;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import com.example.buttoncontrols.util.DateUtil;/*** @author Natural-Pride*/
public class ButtonClickActivity extends AppCompatActivity implements View.OnClickListener {private TextView tvResult;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_button_click);Button btnClickSingle = findViewById(R.id.btn_click_single);Button btnClickPublic = findViewById(R.id.btn_click_public);tvResult = findViewById(R.id.tv_result);btnClickSingle.setOnClickListener(new MyOnClickListener(tvResult));btnClickPublic.setOnClickListener(this);}// 公共的点击事件监听@Overridepublic void onClick(View v) {if (v.getId()==R.id.btn_click_public){String desc=String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(),((Button) v).getText());tvResult.setText(desc);}}// 单独的点击事件监听static class MyOnClickListener implements View.OnClickListener {private final TextView tvResult;public MyOnClickListener(TextView tvResult) {this.tvResult=tvResult;}@Overridepublic void onClick(View view) {String desc=String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(),((Button)view).getText());tvResult.setText(desc);}}
}

实现效果如图:

点击前:

在这里插入图片描述

点击单独的点击监听器:

在这里插入图片描述

点击公共的点击监听器

在这里插入图片描述

2. 长按实践

除了点击事件,Android还设计了另外一种长按事件,每当控件被按住超过500毫秒之后,就会触发该控件的长按事件。若要捕捉按钮的长按事件,可调用按钮对象的setOnLongClickListener方法设置长按监听器。具体的设置代码示例如下:

package com.example.buttoncontrols;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import com.example.buttoncontrols.util.DateUtil;public class ButtonLongActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_button_long);TextView tvResult=findViewById(R.id.tv_result);Button btnLongClick=findViewById(R.id.btn_long_click);btnLongClick.setOnLongClickListener(v -> {String desc=String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(),((Button)v).getText());tvResult.setText(desc);return true;});}
}

再次运行App,长按按钮之后的界面如图所示,说明长按事件果然触发了onLongClick方法。

在这里插入图片描述

值得注意的是,点击监听器和长按监听器不局限于按钮控件,其实它们都来源于视图基类View,凡是从View派生而来的各类控件,均可注册点击监听器和长按监听器。譬如文本视图TextView,其对象也能调用setOnClickListener方法与setOnLongClickListener方法,此时TextView控件就会响应点击动作和长按动作。因为按钮存在按下和松开两种背景,便于提示用户该控件允许点击,但文本视图默认没有按压背景,不方便判断是否被点击,所以一般不会让文本视图处理点击事件和长按事件。

3.4.3 禁用与恢复按钮

尽管按钮控件生来就是给人点击的,可是某些情况希望暂时禁止点击操作,譬如用户在注册的时候,有的网站要求用户必须同意指定条款,而且至少浏览10秒之后才能点击注册按钮。那么在10秒之前,注册按钮应当置灰且不能点击,等过了10秒之后,注册按钮才恢复正常。在这样的业务场景中,按钮先后拥有两种状态,即不可用状态与可用状态,它们在外观和功能上的区别如下:

(1)不可用按钮:按钮不允许点击,即使点击也没反应,同时按钮文字为灰色。

(2)可用按钮:按钮允许点击,点击按钮会触发点击事件,同时按钮文字为正常的黑色。

从上述的区别说明可知,不可用与可用状态主要有两点差异:其一,是否允许点击;其二,按钮文字的颜色。就文字颜色而言,可在布局文件中使用textColor属性设置颜色,也可在Java代码中调用setTextColor方法设置颜色。至于是否允许点击,则需引入新属性android:enabled,该属性值为true时表示启用按钮,即允许点击按钮;该属性值为false时表示禁用按钮,即不允许点击按钮。在Java代码中,则可通过setEnabled方法设置按钮的可用状态(true表示启用,false表示禁用)。

接下来通过一个例子演示按钮的启用和禁用操作。为了改变测试按钮的可用状态,需要额外添加两个控制按钮,分别是“启用测试按钮”和“禁用测试按钮”,加起来一共3个按钮控件,注意“测试按钮”默认是灰色文本。测试界面的布局效果如图所示。

在这里插入图片描述

与图对应的布局文件内容如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".ButtonEnableActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><Buttonandroid:id="@+id/btn_enable"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="启用测试按钮"android:textColor="#000000"android:textSize="17sp" /><Buttonandroid:id="@+id/btn_disable"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:text="禁用测试按钮"android:textColor="#000000"android:textSize="17sp" /></LinearLayout><Buttonandroid:id="@+id/btn_test"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="测试按钮"android:textColor="#888888"android:textSize="17sp"android:enabled="false"/><TextViewandroid:id="@+id/tv_result"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="这里查看测试按钮的点击结果"android:textColor="@color/black"android:textSize="17sp" />
</LinearLayout>

然后在Java代码中给3个按钮分别注册点击监听器,注册代码如下所示:

package com.example.buttoncontrols;import androidx.appcompat.app.AppCompatActivity;import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import com.example.buttoncontrols.util.DateUtil;public class ButtonEnableActivity extends AppCompatActivity implements View.OnClickListener {private Button btnTest;private TextView tvResult;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_button_enable);Button btnEnable = findViewById(R.id.btn_enable);Button btnDisable = findViewById(R.id.btn_disable);btnTest = findViewById(R.id.btn_test);tvResult = findViewById(R.id.tv_result);btnEnable.setOnClickListener(this);btnDisable.setOnClickListener(this);btnTest.setOnClickListener(this);}@Overridepublic void onClick(View v) {int id = v.getId();if (id == R.id.btn_enable) {// 启用当前控件btnTest.setEnabled(true);// 设置按钮的文字颜色btnTest.setTextColor(Color.BLACK);} else if (id == R.id.btn_disable) {// 禁用当前控件btnTest.setEnabled(false);btnTest.setTextColor(Color.GRAY);} else {String desc = String.format("%s 您点击了按钮:%s", DateUtil.getNowTime(), ((Button) v).getText());tvResult.setText(desc);}}
}

最后编译运行App,点击了“启用测试按钮”之后,原本置灰的测试按钮btn_test恢复正常的黑色文本,点击该按钮发现界面有了反应,具体效果如图所示

在这里插入图片描述

对比两图,观察按钮启用前后的外观及其是否响应点击动作,即可知晓禁用按钮和启用按钮两种模式的差别。

3.5 图像显示

本节介绍了与图像显示有关的几种控件用法,包括:专门用于显示图片的图像视图以及若干缩放类型效果,支持显示图片的按钮控件——图像按钮,如何在按钮控件上同时显示文本和图标等。

3.5.1 图像视图ImageView

显示文本用到了文本视图TextView,显示图像则用到图像视图ImageView。由于图像通常保存为单独的图片文件,因此需要先把图片放到res/drawable目录,然后再去引用该图片的资源名称。比如现在有张图片名为laugh.png,那么XML文件通过属性android:src设置图片资源,属性值格式形如“@drawable/不含扩展名的图片名称”。添加了src属性的ImageView标签示例如下:

  <ImageViewandroid:id="@+id/iv_scale"android:layout_width="match_parent"android:layout_height="220dp"android:src="@drawable/laugh" />

若想在Java代码中设置图像视图的图片资源,可调用ImageView控件的setImageResource方法,方法参数格式形如“R.drawable.不含扩展名的图片名称”。仍以上述的苹果图片为例,给图像视图设置图片资源的代码例子如下所示:

package com.example.imagedisplay;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.widget.ImageView;public class ImageScaleActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_image_scale);ImageView ivScale= findViewById(R.id.iv_scale);ivScale.setImageResource(R.drawable.laugh);}
}

运行测试App,展示图片的界面效果如图所示

在这里插入图片描述

观察效果图发现图片居中显示,而非文本视图里的文字那样默认靠左显示,这是怎么回事?

原来ImageView本身默认图片居中显示,不管图片有多大抑或有多小,图像视图都会自动缩放图片,使之刚好够着ImageView的边界,并且缩放后的图片保持原始的宽高比例,看起来图片很完美地占据视图中央。

这种缩放类型在XML文件中通过属性android:scaleType定义,即使图像视图未明确指定该属性,系统也会默认其值为fitCenter,表示让图像缩放后居中显示。添加了缩放属性的ImageView标签如下所示:

  <ImageViewandroid:id="@+id/iv_scale"android:layout_width="match_parent"android:layout_height="220dp"android:src="@drawable/laugh"android:scaleType="fitCenter"/>

在Java代码中可调用setScaleType方法设置图像视图的缩放类型,其中fitCenter对应的类型为ScaleType.FIT_CENTER,设置代码示例如下:

// 将缩放类型设置为“保持宽高比例,缩放图片使其位于视图中间”
iv_scale.setScaleType(ImageView.ScaleType.FIT_CENTER);

除了居中显示,图像视图还提供了其他缩放类型,详细的缩放类型取值说明见表

在这里插入图片描述

3.5.2 图像按钮ImageButton

常见的按钮控件Button其实是文本按钮,因为按钮上面只能显示文字,不能显示图片,ImageButton才是显示图片的图像按钮。虽然ImageButton号称图像按钮,但它并非继承Button,而是继承了ImageView,所以凡是ImageView拥有的属性和方法,ImageButton统统拿了过来,区别在于ImageButton有个按钮背景。

尽管ImageButton源自ImageView,但它毕竟是个按钮呀,按钮家族常用的点击事件和长按事件,ImageButton全都没落下。不过ImageButton和Button之间除了名称不同,还有下列差异:

  • Button既可显示文本也可显示图片(通过setBackgroundResource方法设置背景图片),而ImageButton只能显示图片不能显示文本。

  • ImageButton上的图像可按比例缩放,而Button通过背景设置的图像会拉伸变形,因为背景图采取fitXY方式,无法按比例缩放。

  • Button只能靠背景显示一张图片,而ImageButton可分别在前景和背景显示图片,从而实现两张图片叠加的效果。

从上面可以看出,Button与ImageButton各有千秋,通常情况使用Button就够用了。但在某些场合,比如输入法打不出来的字符,以及特殊字体显示的字符串,就适合先切图再放到ImageButton。

举个例子,数学常见的开平方运算,由输入法打出来的运算符号为“√”,但该符号缺少右上角的一横,正确的开平方符号是带横线的,此时便需要通过ImageButton显示这个开方图片。不过使用ImageButton得注意,图像按钮默认的缩放类型为center(保持原始尺寸不缩放图片),而非图像视图默认的fitCenter,倘若图片尺寸较大,那么图像按钮将无法显示整个图片。为避免显示不完整的情况,XML文件中的ImageButton标签必须指定fitCenter的缩放类型,详细的标签内容示例如下:

  <ImageButtonandroid:layout_width="match_parent"android:layout_height="80dp"android:src="@drawable/sqrt"android:scaleType="fitCenter" />

打开演示界面如图所示,可见图像按钮正确展示了开平方符号

在这里插入图片描述

3.5.3 同时展示文本与图像

现在有了Button可在按钮上显示文字,又有ImageButton可在按钮上显示图像,照理说绝大多数场合都够用了。然而现实项目中的需求往往捉摸不定,例如客户要求在按钮文字的左边加一个图标,这样按钮内部既有文字又有图片,乍看之下Button和ImageButton都没法直接使用。若用LinearLayout对ImageView和TextView组合布局,虽然可行,XML文件却变得冗长许多。

其实有个既简单又灵活的办法,要想在文字周围放置图片,使用按钮控件Button就能实现。原来Button悄悄提供了几个与图标有关的属性,通过这些属性即可指定文字旁边的图标,以下是有关的图标属性说明。

  • drawableTop:指定文字上方的图片。

  • drawableBottom:指定文字下方的图片。

  • drawableLeft:指定文字左边的图片。

  • drawableRight:指定文字右边的图片。

  • drawablePadding:指定图片与文字的间距。

譬如下面是个既有文字又有图标的Button标签例子:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".ImageTextActivity"><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="图标在左"android:drawableStart="@drawable/error"android:background="#FFFFFF"android:drawablePadding="5dp"/></LinearLayout>

效果如下图:

在这里插入图片描述
本章节其他文章
Android App开发-简单控件(1)—— 文本显示
Android App开发-简单控件(2)—— 视图基础
Android App开发-简单控件(3)—— 常用布局
Android App开发-简单控件(4)—— 按钮触控和图像显示

本笔记参考于[B站动脑学院],仅作学习用途,方便随时查看。
参考资料:2022 最新Android基础教程,从开发入门到项目实战,看它就够了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/434959.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在autodl训练yolov8时卡在下载字体

1.问题 在autodl训练yolov8到这一步之后会卡住很久 2. 解决办法 Ctric中断后发现是下载Arial字体卡住了&#xff0c;这个字体需要从外网中下载 先手动从链接中下载https://ultralytics.com/assets/Arial.ttf &#xff0c;然后上传到autodl。然后将这个文件移动到/root/.config/…

vusui css 使用,简单明了 适合后端人员 已解决

vusui-cssopen in new window 免除开发者繁复的手写 CSS 样式&#xff0c;让 WEB 前端开发更简单、灵活、便捷&#xff01;如果喜欢就点个 ★Staropen in new window 吧。 移动设备优先&#xff1a; vusui-css 包含了贯穿于整个库的移动设备优先的样式。浏览器支持&#xff1a…

数据结构.单链表

1.单链表&#xff08;有头结点&#xff0c;无头节点&#xff09; 2.插入 不带头结点的处理起来会麻烦一些。 3.删除 4.查找 5.建立链表 6.头插法可以用来实现链表的逆置 代码&#xff1a; #include<iostream> using namespace std; const int N 10; typedef struct LNod…

【鸿蒙】大模型对话应用(二):对话界面设计与实现

Demo介绍 本demo对接阿里云和百度的大模型API&#xff0c;实现一个简单的对话应用。 DecEco Studio版本&#xff1a;DevEco Studio 3.1.1 Release HarmonyOS SDK版本&#xff1a;API9 关键点&#xff1a;ArkTS、ArkUI、UIAbility、网络http请求、列表布局、层叠布局 对话页…

【UE5】如何给人物骨骼绑定Control Rig用来制作动画(控制)

本篇文章暂时只教绑定人物手部的Control Rig&#xff0c;脚的Control Rig举一反三即可 1&#xff0c;右键-创建-控制绑定 2在控制绑定中-右键创建基本IK 3&#xff0c;填入上臂-下臂-手 4【手和下臂】右键-新建-Add Controls For Selected&#xff0c;&#xff08;或者新建-…

【C++】std::variant

上一篇文章讲到了 union&#xff0c;union union存在很多问题&#xff0c;因此C17设计了一个新的variant替代原来的union。 union的问题 无法知道当前使用的类型是什么。而且union无法自动调用底层数据成员的析构函数。 这些使得一般只对一些“基本类型”使用union&#xf…

springboot通过ftl模板动态生成图片字体异常加载字体文件

针对上篇文章springboot通过ftl模板动态生成图片&#xff08;html生成图片imgBase64&#xff09;有不少小伙伴问生成的图片字体异常&#xff0c;或者本地正常服务器异常&#xff0c;我这里有一个优化&#xff0c;给字体文件放在项目中自己加载即可 响应的调整&#xff1a; POM…

2024年阿里云幻兽帕鲁Palworld游戏服务器优惠价格表

自建幻兽帕鲁服务器租用价格表&#xff0c;2024阿里云推出专属幻兽帕鲁Palworld游戏优惠服务器&#xff0c;配置分为4核16G和4核32G服务器&#xff0c;4核16G配置32.25元/1个月、10M带宽66.30元/1个月、4核32G配置113.24元/1个月&#xff0c;4核32G配置3个月339.72元。ECS云服务…

【RT-DETR有效改进】反向残差块网络EMO | 一种轻量级的CNN架构(轻量化网络,参数量下降约700W)

前言 大家好&#xff0c;这里是RT-DETR有效涨点专栏。 本专栏的内容为根据ultralytics版本的RT-DETR进行改进&#xff0c;内容持续更新&#xff0c;每周更新文章数量3-10篇。 专栏以ResNet18、ResNet50为基础修改版本&#xff0c;同时修改内容也支持ResNet32、ResNet101和PP…

MongoDB:从容器使用到 Mongosh、Python/Node.js 数据操作

文章目录 1. 容器与应用之间的关系介绍2. 使用 Docker 容器安装 MongoDB3. Mongosh 操作3.1 Mongosh 连接到 MongoDB3.2 基础操作与 CRUD 4. Python 操作 MongoDB5. Nodejs 操作 MongoDB参考文献 1. 容器与应用之间的关系介绍 MongoDB 的安装有时候并不是那么容易的&#xff0…

如何在有或没有备份的 iPhone 上检索已删除的短信

iPhone 清理垃圾短信时不小心删除了一些重要短信&#xff1f;想知道如何找回 iPhone 上已删除的短信吗&#xff1f;如果您已将设备备份到 iCloud 或 iTunes&#xff0c;则可以从备份恢复 iPhone 上的短信。如果没有备份&#xff0c;您可以尝试第三方iPhone短信恢复程序来恢复它…

Android如何通过按钮实现页面跳转方法

Hello大家好&#xff01;我是咕噜铁蛋&#xff01;在Android应用开发中&#xff0c;页面跳转是一项基本且常见的功能。通过按钮实现页面跳转可以为用户提供更好的交互体验&#xff0c;使应用更加灵活和易用。本文将介绍Android Studio中如何通过按钮实现页面跳转的方法&#xf…