Android中级——屏幕和绘图

news2025/2/28 15:26:03

屏幕和绘图

  • 屏幕
    • 系统屏幕密度
    • 独立像素密度dp
    • 单位转换
  • XML绘图(需放在Drawable)
    • Bitmap
    • Shape
    • Layer
    • Selector
  • 绘图技巧
    • Canvas
    • Layer
    • PorterDuffXfermode
    • Shader
    • PathEffect
    • SurfaceView

屏幕

  • 屏幕大小:指屏幕对角线长度,单位为寸
  • 分辨率:指屏幕宽高的像素点个数,如720x1280
  • PPI:每英寸像素(Pixels Per Inch),指对角线的像素点数除以屏幕大小,又称屏幕密度DPI(Dots Per Inch)

系统屏幕密度

不同手机的大小和像素密度都不同,为统一,定义了几个标准的DPI值

在这里插入图片描述

独立像素密度dp

相同的像素,在不同密度的屏幕上显示,长度会不同,因为高密度的屏幕包含更多像素点

  • 规定密度为mdpi(即密度值为160)时1px=1dp
  • 故上图各分辨率的换算比例为3:4:6:8:12

单位转换

如下工具类提供了px、dp、sp的互相转换

public class DisplayUtil {
    // dp = 像素/密度
    public static int px2dip(Context context, float pxValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    public static int dip2px(Context context, float dipValue) {
        float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    // sp = 像素/缩放密度
    public static int px2sp(Context context, float pxValue) {
        float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
    }

    public static int sp2px(Context context, float spValue) {
        float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }
}

或可以使用TypedValue.applyDimension()方法

public int dp2px(int dp) {
    return (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            dp,
            getResources().getDisplayMetrics());
}

public int sp2px(int sp) {
    return (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_SP,
            sp,
            getResources().getDisplayMetrics());
}

XML绘图(需放在Drawable)

Bitmap

如下引用图片并转为Bitmap

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@mipmap/ic_launcher" />

Shape

Shape可实现不同类型的形状,如下实现渐变阴影

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <gradient
        android:angle="45"
        android:endColor="#805FBBFF"
        android:startColor="#FF5DA2FF" />
    <padding
        android:bottom="7dp"
        android:left="7dp"
        android:right="7dp"
        android:top="7dp" />
    <corners android:radius="8dp" />
</shape>

效果如图

在这里插入图片描述

Layer

Layer可实现类似PS中图层的概念

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/ic_launcher" />
    <item
        android:bottom="50dp"
        android:drawable="@mipmap/ic_launcher"
        android:left="50dp"
        android:right="50dp"
        android:top="50dp" />
</layer-list>

上面两个item分别为图片进行叠加,效果如图

在这里插入图片描述

Selector

Selector实现不同事件设置反馈,如下实现修改为圆角矩形,点击后切换颜色

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#33444444" />
            <corners android:radius="5dp" />
            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
        </shape>
    </item>

    <item>
        <shape android:shape="rectangle">
            <solid android:color="#FFFFFF" />
            <corners android:radius="5dp" />
            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
        </shape>
    </item>
</selector>

绘图技巧

Canvas

下面为常用的方法

  • save():将已绘制图像保存,在此之后的操作绘制在新图层
  • restore():合并图层,将save()之后绘制的图像和save()之前的合并
  • translate():坐标系平移
  • ratate():坐标系旋转

如下绘制一个时钟,通过平移、旋转坐标系简化实现

public class Clock extends View {


    private int mWidth;
    private int mHeight;

    public Clock(Context context) {
        super(context);
    }

    public Clock(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public Clock(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 绘制外圆,以(mWidth / 2, mHeight / 2)为圆形,以mWidth / 2为半径
        Paint paintCircle = new Paint();
        paintCircle.setStyle(Paint.Style.STROKE);
        paintCircle.setAntiAlias(true);
        paintCircle.setStrokeWidth(5);
        canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, paintCircle);

        // 绘制刻度
        Paint paintDegree = new Paint();
        for (int i = 0; i < 24; i++) {
            if (i == 0 || i == 6 || i == 12 || i == 18) {
                paintDegree.setStrokeWidth(5);
                paintDegree.setTextSize(30);
                canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,
                        mWidth / 2, mHeight / 2 - mWidth / 2 + 60,
                        paintDegree);
                String degree = String.valueOf(i);
                canvas.drawText(degree,
                        mWidth / 2 - paintDegree.measureText(degree) / 2,
                        mHeight / 2 - mWidth / 2 + 90,
                        paintDegree);
            } else {
                paintDegree.setStrokeWidth(3);
                paintDegree.setTextSize(15);
                canvas.drawLine(mWidth / 2, mHeight / 2 - mWidth / 2,
                        mWidth / 2, mHeight / 2 - mWidth / 2 + 30,
                        paintDegree);
                String degree = String.valueOf(i);
                canvas.drawText(degree,
                        mWidth / 2 - paintDegree.measureText(degree) / 2,
                        mHeight / 2 - mWidth / 2 + 60,
                        paintDegree);
            }
            // 将画布以圆心旋转15°,简化坐标运算
            canvas.rotate(15, mWidth / 2, mHeight / 2);
        }

        // 绘制指针
        Paint paintHour = new Paint();
        paintHour.setStrokeWidth(20);
        Paint paintMinute = new Paint();
        paintMinute.setStrokeWidth(10);
        canvas.save();

        canvas.translate(mWidth / 2, mHeight / 2); // 将坐标系平移到圆点,再画指针
        canvas.drawLine(0, 0, 100, 100, paintHour);
        canvas.drawLine(0, 0, 100, 200, paintMinute);
        canvas.restore();
    }
}

Layer

图层基于栈结构,入栈后操作都发生在该图层上,出栈后则把图像绘制到上层Canvas

  • 入栈:saveLayer()、saveLayerAlpha()
  • 出栈:restore()、restoreToCount()
public class MyView extends View {

    private static final String TAG = MyView.class.getSimpleName();
    private Paint mPaint;

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mPaint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.WHITE);
        mPaint.setColor(Color.BLUE);
        canvas.drawCircle(150, 150, 100, mPaint);

        canvas.saveLayerAlpha(0, 0, 400, 400, 127);
        mPaint.setColor(Color.RED);
        canvas.drawCircle(200, 200, 100, mPaint);
        canvas.restore();
    }
}

如下图,透明度为127的红色圆叠加在蓝色圆上方

在这里插入图片描述

PorterDuffXfermode

PorterDuffXfermod设置的是两个图层交集区域的显示方式,dst是先画的图形,而src是后画的图形,共有16种模式,如图

在这里插入图片描述

如下实现圆角图形,mOut为先画的图像,mBitmap为后画的图像,用SrcIn取交集

public class MyView extends View {

    private static final String TAG = MyView.class.getSimpleName();
    private Bitmap mBitmap;
    private Bitmap mOut;
    private Paint mPaint;

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
        mOut = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(mOut);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        canvas.drawRoundRect(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), 80, 80, mPaint);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(mBitmap, 0, 0, mPaint);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(mOut, 0, 0, null);
    }
}

效果如图

在这里插入图片描述

如下代码设置透明的画笔,实时获取坐标调用drawPath()涂抹上面的图层,实现刮刮乐

public class XfermodeView extends View {

    private Bitmap mBgBitmap, mFgBitmap;
    private Paint mPaint;
    private Canvas mCanvas;
    private Path mPath;

    public XfermodeView(Context context) {
        this(context, null);
    }

    public XfermodeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public XfermodeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAlpha(0);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeWidth(50);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPath = new Path();
        mBgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.b);
        mFgBitmap = Bitmap.createBitmap(mBgBitmap.getWidth(), mBgBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mFgBitmap);
        mCanvas.drawColor(Color.GRAY);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPath.reset();
                mPath.moveTo(event.getX(), event.getY());
                break;
            case MotionEvent.ACTION_MOVE:
                mPath.lineTo(event.getX(), event.getY());
                break;
        }
        mCanvas.drawPath(mPath, mPaint);
        invalidate();
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(mBgBitmap, 0, 0, null);
        canvas.drawBitmap(mFgBitmap, 0, 0, null);
    }
}

在这里插入图片描述

Shader

用于实现渐变、渲染效果,包括

  • BitmapShader——位图Shader
  • LinnerGradient——线性Shader
  • RadialGradient——光束Shader
  • SweepGradient——梯度Shader
  • ComposeShader——混合Shader

上述渐变都有三种模式选择:

  • CLAMP:拉伸,拉伸的是图片最后一个像素,不断重复
  • REPEAT:重复,横向、纵向不断重复
  • MIRROR:镜像,横向、纵向不断翻转重复

如下,将图片填充到BitmapShader,创建一支具有图像填充功能的Paint

public class MyView extends View {

    private static final String TAG = MyView.class.getSimpleName();
    private Bitmap mBitmap;
    private Paint mPaint;
    private BitmapShader mBitmapShader;

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
        mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        mPaint = new Paint();
        mPaint.setShader(mBitmapShader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(mBitmap.getWidth() / 2.0f, mBitmap.getHeight() / 2.0f, 50, mPaint);
    }
}

利用Paint在图片中心绘制圆形,效果如下

在这里插入图片描述
如下改为REPEAT,并扩大半径,可看到图片不断重复绘制

public class MyView extends View {

    private static final String TAG = MyView.class.getSimpleName();
    private Bitmap mBitmap;
    private Paint mPaint;
    private BitmapShader mBitmapShader;

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
        mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        mPaint = new Paint();
        mPaint.setShader(mBitmapShader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(mBitmap.getWidth() / 2.0f, mBitmap.getHeight() / 2.0f, 500, mPaint);
    }
}

在这里插入图片描述

如下利用PorterDuffXfermode和LinnerGradient实现倒影效果的图片

public class ReflectView extends View {
    private Bitmap mSrcBitmap, mRefBitmap;
    private Paint mPaint;
    private PorterDuffXfermode mXfermode;

    public ReflectView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mSrcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.b);

        Matrix matrix = new Matrix();
        matrix.setScale(1F, -1F);//垂直翻转

        mRefBitmap = Bitmap.createBitmap(mSrcBitmap, 0, 0,
                mSrcBitmap.getWidth(), mSrcBitmap.getHeight(), matrix, true);

        mPaint = new Paint();
        mPaint.setShader(new LinearGradient(0, mSrcBitmap.getHeight(),
                0, mSrcBitmap.getHeight() * 2,
                0xDD000000, 0x10000000, Shader.TileMode.REPEAT));

        mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.BLACK);
        //原图
        canvas.drawBitmap(mSrcBitmap, 0, 0, null);
        //倒影图
        canvas.drawBitmap(mRefBitmap, 0, mSrcBitmap.getHeight(), null);

        mPaint.setXfermode(mXfermode);
        //绘制渐变效果层
        canvas.drawRect(0, mRefBitmap.getHeight(), mRefBitmap.getWidth(), mSrcBitmap.getHeight() * 2, mPaint);
        mPaint.setXfermode(null);
    }
}

先将图片翻转,再添加黑色透明度递减的渐变,DST_IN是为了避免上面的图像被渐变效果遮挡

在这里插入图片描述

PathEffect

PathEffect指用各种笔触效果来绘制一个路径
在这里插入图片描述

如上,分别为

  • 无效果
  • CornerPathEffect:线段拐角圆滑
  • DiscretePathEffect:线段出现杂点
  • DashPathEffect:绘制虚线,用一个数组来设置各个点之间的间隔,还可设置偏移量实现动态路径效果
  • PathPathEffect:类似DashPathEffect,但还可设置点的图形,如上面的圆点虚线
  • ConposePathEffect:组合效果
public class MyView extends View {

    private static final String TAG = MyView.class.getSimpleName();
    private Path mPath;
    private PathEffect[] mPathEffect;
    private Paint mPaint;

    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPath = new Path();
        mPath.moveTo(0, 0);
        for (int i = 0; i <= 30; i++) {
            mPath.lineTo(i * 35, (float) (Math.random() * 100));
        }
        mPathEffect = new PathEffect[6];
        mPathEffect[0] = null;
        mPathEffect[1] = new CornerPathEffect(30);
        mPathEffect[2] = new DiscretePathEffect(3.0F, 5.0F);
        mPathEffect[3] = new DashPathEffect(new float[]{20, 10, 5, 10}, 0);
        Path path = new Path();
        path.addRect(0, 0, 8, 8, Path.Direction.CCW);
        mPathEffect[4] = new PathDashPathEffect(path, 12, 0, PathDashPathEffect.Style.ROTATE);
        mPathEffect[5] = new ComposePathEffect(mPathEffect[3], mPathEffect[1]);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (PathEffect pathEffect : mPathEffect) {
            mPaint.setPathEffect(pathEffect);
            canvas.drawPath(mPath, mPaint);
            canvas.translate(0, 200);
        }
    }
}

SurfaceView

Android通过VSYNC信号刷新View进行屏幕的重绘,时间间隔为16ms,若在需要频繁刷新的界面上执行太多的操作逻辑,则容易阻塞主线程,造成画面卡顿

当需要频繁刷新或刷新时数据处理量比较大时,可使用SurfaceView

  • View用于主动刷新,SurfaceView用于被动刷新
  • View在主线程刷新,SurfaceView在子线程刷新
  • View绘图未使用双缓冲机制,SurfaceView则使用双缓冲机制

SurfaceView的模板代码如下,主要原理是初始化时自行创建子线程并调用draw()方法绘制

public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    //内部Holder,用于获取Canvas和提交绘制
    private SurfaceHolder mHolder;
    //用于控制线程的标志位
    private boolean mIsDrawing;
    //用于绘图的Canvas
    private Canvas mCanvas;

    public SurfaceViewTemplate(Context context) {
        this(context, null);
    }

    public SurfaceViewTemplate(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SurfaceViewTemplate(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mHolder = getHolder();
        mHolder.addCallback(this);  //将自身作为回调

        setFocusableInTouchMode(true);
        setFocusable(true);

        this.setKeepScreenOn(true);
    }

    //创建时开启线程,调用draw()
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsDrawing = true;

        new Thread(this).start();
    }

    //改变时回调
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    //结束时回调
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDrawing = false;
    }

    @Override
    public void run() {
        while (mIsDrawing) {
            draw();
        }
    }

    private void draw() {
        try {
            mCanvas = mHolder.lockCanvas();
            //获取Canvas开始绘制,获取的并非新的Canvas,而是上次的
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (mHolder != null) {
                //绘制完后需提交
                mHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    }
}

如下代码利用SurfaceView实现正弦函数的动态绘制

public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    private SurfaceHolder mHolder;
    private boolean mIsDrawing;
    private Canvas mCanvas;
    private int x;
    private int y;
    private Path mPath;
    private Paint mPaint;

    public SurfaceViewTemplate(Context context) {
        this(context, null);
    }

    public SurfaceViewTemplate(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SurfaceViewTemplate(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPath = new Path();
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);

        mHolder = getHolder();
        mHolder.addCallback(this);

        setFocusableInTouchMode(true);
        setFocusable(true);

        this.setKeepScreenOn(true);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsDrawing = true;

        new Thread(this).start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDrawing = false;
    }

    @Override
    public void run() {
        while (mIsDrawing) {
            draw();
            x += 1;
            y = (int) (100 * Math.sin(x * 2 * Math.PI / 180) + 400);
            mPath.lineTo(x, y);
        }
    }

    private void draw() {
        try {
            mCanvas = mHolder.lockCanvas();
            mCanvas.drawColor(Color.WHITE); //设置背景
            mCanvas.drawPath(mPath, mPaint);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (mHolder != null) {
                mHolder.unlockCanvasAndPost(mCanvas);
            }
        }
    }
}

效果如图

在这里插入图片描述

如下代码利用SurfaceView实现绘图板,根据手指移动绘制路径,在draw()中调用sleep()避免过度频繁绘制

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

管理类书籍推荐

管理类书籍对于每一位想要获得管理能力提升或者实现职业生涯更上一层楼的企业管理者或领导者而言&#xff0c;都是不可或缺的一项重要学习工具。作为管理工作从事者的职场必需品&#xff0c;一本出色的管理类书籍可以为我们提供大量宝贵的经验与专业建议&#xff0c;从而让管理…

ChatGPT助力校招----面试问题分享(二)

1 ChatGPT每日一题&#xff1a;DC-DC与LDO的区别 问题&#xff1a;介绍一下DC-DC与LDO的区别 ChatGPT&#xff1a;DC-DC和LDO都是电源管理电路&#xff0c;它们的主要作用是将输入电压转换为所需的输出电压&#xff0c;以供电子设备使用。但是&#xff0c;它们之间存在一些重…

GlassFish的安装与使用

一、产品下载与安装glassfish下载地址&#xff1a;https://download.oracle.com/glassfish/5.0.1/release/index.html下载后解压即完成安装&#xff0c;主要目录说明&#xff1a;bin目录&#xff1a;为asadmin命令所在目录。glassfish为主目录&#xff1a;glassfish\bin目录为命…

C++基础了解-13-C++ 数组

C 数组 一、C 数组 C 支持数组数据结构&#xff0c;它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据&#xff0c;但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量&#xff0c;比如 number0、number1、…、number9…

Android特别的数据结构(一) SparseArray源码解析

1.数据结构 class SparseArray<E> implements Cloneable 由两个数组构成&#xff0c;一个数组mKeys类型为int[]&#xff0c;存放Key&#xff0c;一个数组mValues类型为 E[]&#xff0c;存放Value。Key数组升序排列。默认初始容量&#xff1a;10扩容&#xff1a; 如果当…

Hbuilder 下载与安装教程

文章目录Hbuilder下载与安装教程Hbuilder简介一&#xff0c;下载Hbuilder二&#xff0c;安装Hbuilder三&#xff0c;简单使用四&#xff0c;Hbuilderx 调试Hbuilder下载与安装教程 Hbuilder简介 Builder是DCloud&#xff08;数字天堂&#xff09;推出的一款支持HTML5的Web开发…

你还在手撸SQL?ChatGPT笑晕在厕所

文章目录你还在手撸SQL&#xff1f;ChatGPT笑晕在厕所一、背景二、面向Chat编程1. 数据库设计2. 建表语句3. 加中文注释4. 数据模拟5. 查询成绩6. 修改课程任课老师7. 删除课程8. 删除一个有关联数据的课程总结你还在手撸SQL&#xff1f;ChatGPT笑晕在厕所 一、背景 经典3表设…

【项目精选】基于SSH的医院在线挂号系统(视频+论文+源码)

点击下载源码 医院挂号系统主要用于实现医院的挂号&#xff0c;前台基本功能包括&#xff1a;用户注册、用户登录、医院查询、挂号、取消挂号、修改个人信息、退出等。 后台基本功能包括&#xff1a;系统管理员登录、医院管理、科室管理、公告管理、退出系统等。 本系统结构如…

图文讲解MongoDB该怎么安装

一、安装前必读 我这里是Centos7 Linux 内核 注意&#xff1a;本文的命令使用的是 root 用户登录执行&#xff0c;不是 root 的话所有命令前面要加 sudo 二、环境配置 2.1 停止防火墙 systemctl status firewalld #查看firewall systemctl stop firewalld …

Vector - CAPL - 测试报告函数介绍

测试报告是我们开发脚本中必备的一个模块,今天我们介绍一下测试报告中的常用函数,让我们开发出更加清晰、美观的报告,让我们的测试工作更加轻松。 TestCaseComment

备战蓝桥python——完全平方数

完全平方数 链接: 完全平方数 暴力解法&#xff1a; n int(input()) for i in range(1, n1):if(((i*n)**0.5)%10.0):print(i)break运用数论相关知识求解 任意一个正整数都可以被分解成若干个质数乘积的形式&#xff0c;例如 :2022∗5120 \ 2^{2}*5^{1}\,20 22∗51 由此…

JVM的了解与学习

一:jvm是什么 jvm是java虚拟机java Virtual Machine的缩写 jdk包含jre和java DevelopmentTools 二:什么是java虚拟机 虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。java虚拟机有自己完善的硬体结构,如处理器、堆栈、寄存器等,还有…

Hive映射Hbase

依赖条件 已有Hadoop、Hive、Zookeeper、HBase 环境。 为什么Hive要映射Hbase HBase 只提供了简单的基于 Key 值的快速查询能力&#xff0c;没法进行大量的条件查询&#xff0c;对于数据分析来说&#xff0c;不太友好。 hive 映射 hbase 为用户提供一种 sqlOnHbase 的方法。…

zookeeper 集群配置

文章目录zookeeper 集群配置1、集群安装zookeeper 集群配置 1、集群安装 1) 集群安装 在 hadoop102、hadoop103 和 hadoop104 三个节点上都部署 Zookeeper。 2) 解压安装 在 hadoop102 解压 Zookeeper 安装包到/opt目录下 输入命令&#xff1a;tar -zxvf apache-zookeeper-3.…

C++——IO流

目录 C语言的输入与输出 流是什么 CIO流 C标准IO流 C文件IO流 二进制读写 文本读写 stringstream的简单介绍 C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输入设备(键 盘)读取数据&#xff0c;并将值存放在变量中。…

自学大数据第5天~hadoop集群搭建(二)

配置集群/分布式环境 1,修改文件workers 需要把所有节点数据节点的主机名写入该文件,每行一个,默认localhost(即把本机(namenode也作为数据节点),所以我们在伪分布式是没有配置该文件; 在进行分布式时需要删掉localhost(又可能文件中没有该配置,没有那就不用删了,配置一下数据…

147597-66-8,p-SCN-Bn-NOTA,NOTA-P-苯-NCS新型双功能螯合剂

p-SCN-Bn-NOTA | NOTA-P-苯-NCS | CAS&#xff1a;147597-66-8 | 纯度&#xff1a;95%1.p-SCN-Bn-NOTA试剂信息&#xff1a;CAS号&#xff1a;147597-66-8外观&#xff1a;白色固体分子量&#xff1a;C20H26N4O6S分子式&#xff1a;448.4928溶解性&#xff1a;溶于有机溶剂&…

Java语法中的方法引用::是个什么鬼?

1.函数式接口 函数式接口&#xff08;Functional Interface&#xff09;就是一个有且仅有一个抽象方法&#xff08;通俗来说就是只有一个方法要去被实现&#xff0c;因此我们也能通过这个去动态推断参数类型&#xff09;&#xff0c;但是可以拥有多个非抽象方法的接口。函数式接…

大数据架构设计与数据计算流程

大数据架构设计Hadoop有3个核心组件&#xff1a;分布式文件系统HDFS&#xff1b;分布式运算编程框架MapReduce&#xff1b;分布式资源调度平台YARN。HBase&#xff0c;Hadoop dataBase&#xff0c;基于HDFS的NoSQL数据库&#xff0c;面向列式的内存存储&#xff0c;定期将内存数…

基于MyBatis依次、批量、分页增删改查

我们知道处理数据有三种思路&#xff1a;依次、批量、分页&#xff0c;对应方法如下 依次处理&#xff1a;在 Java 里面写 for 循环&#xff0c;依次使用 SQL 语句&#xff0c;频繁连接断开数据库批量处理&#xff1a;在 MyBatis 里面用 <foreach> 拼接成一条长 SQL 语句…