安卓开发个人小作品(3) – 多功能音乐播放器[通俗易懂]

安卓开发个人小作品(3) – 多功能音乐播放器[通俗易懂]这次介绍一个多功能音乐播放器,记得是大二那年寒假写的,实现的主要功能就是音乐播放,带进度条控制,扫描本地音乐,上一曲下一曲,播放类型(单曲循环,顺序播放,随机播放),APP主题换肤,背景图更换等,功能都比较基础,基本上如果你不会的话,跟着我的思路,应该都是能实现的,预计会在以后加入歌词的功能。在开始前,先放一张最后的效果图吧,我个人喜欢的风格,简约,美观。目录1.实现扫描本地音乐…

大家好,又见面了,我是你们的朋友全栈君。

这次介绍一个多功能音乐播放器,记得是大二那年寒假写的,实现的主要功能就是音乐播放,带进度条控制,扫描本地音乐,上一曲下一曲,播放类型(单曲循环,顺序播放,随机播放),APP主题换肤,背景图更换等,功能都比较基础,基本上如果你不会的话,跟着我的思路,应该都是能实现的,预计会在以后加入歌词的功能。

在开始前,先放一张最后的效果图吧,我个人喜欢的风格,简约,美观。

安卓开发个人小作品(3) - 多功能音乐播放器[通俗易懂]

目录

1.实现扫描本地音乐

2.音乐的播放与控制

3.关联进度条seekbar,自定义seekbar

4.单曲循环,顺序播放,随机播放的实现

5.设置喜爱音乐

6.播放列表背景图设置与保存

7.实现APP主题换肤的功能

正文

1.实现扫描本地音乐

这里为了将每个系统里面存放的音乐抽象出来,也是为了方便管理,先定义一个音乐类Song,代码如下

public class Song {
	/** * 歌手 */
	private String singer;
	/** * 歌曲名 */
	private String song;
	/** * 歌曲的地址 */
	private String path;
	/** * 歌曲长度 */
	private int duration;
	/** * 歌曲的大小 */
	private long size;

	public String getSinger() {
		return singer;
	}

	public void setSinger(String singer) {
		this.singer = singer;
	}

	public String getSong() {
		return song;
	}

	public void setSong(String song) {
		this.song = song;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public int getDuration() {
		return duration;
	}

	public void setDuration(int duration) {
		this.duration = duration;
	}

	public long getSize() {
		return size;
	}

	public void setSize(long size) {
		this.size = size;
	}
}

然后我们再写一个工具类,这个工具类实现的功能就是扫描系统中的本地音乐,返回一个List<Song>集合,供我们使用,代码如下

public class MusicUtils {
	/**
	 * 扫描系统里面的音频文件,返回一个list集合
	 */
	public static List<Song> getMusicData(Context context) {
		List<Song> list = new ArrayList<>();
		Cursor cursor = context.getContentResolver().query(
				MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null,
				MediaStore.Audio.AudioColumns.IS_MUSIC);
		if (cursor != null) {
			while (cursor.moveToNext()) {
				Song song = new Song();
				song.setSong( cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME)));
				song.setSinger( cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST)));
				song.setPath(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)));
				song.setDuration( cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION)));
				song.setSize( cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE)));
				if (song.getSize() > 1000 * 800) {//过滤掉短音频
					// 分离出歌曲名和歌手
					if (song.getSong().contains("-")) {
						String[] str = song.getSong().split("-");
						song.setSinger( str[0]);
						song.setSong( str[1]);
					}
					list.add(song);
				}
			}
			// 释放资源
			cursor.close();
		}
		return list;
	}

	//格式化时间
	public static String formatTime(int time) {
		if (time / 1000 % 60 < 10) {
			return time / 1000 / 60 + ":0" + time / 1000 % 60;
		} else {
			return time / 1000 / 60 + ":" + time / 1000 % 60;
		}
	}
}

然后,在布局里定义一个Listview,再给Listview写一个适配器,一般继承自BaseAdapter,adapter代码如下

public class MyAdapter extends BaseAdapter {
	private Context context;
	private List<Song> list;
	private int position_flag = 0;

	public MyAdapter(MainActivity mainActivity, List<Song> list) {
		this.context = mainActivity;
		this.list = list;
	}

	@Override
	public int getCount() {
		return list.size();
	}

	@Override
	public Object getItem(int i) {
		return list.get(i);
	}

	@Override
	public long getItemId(int i) {
		return i;
	}

	@Override
	public View getView(int i, View view, ViewGroup viewGroup) {

		ViewHolder holder = null;
		if (view == null) {
			holder = new ViewHolder();
			// 引入布局
			view = View.inflate(context, R.layout.list_item, null);
			// 实例化对象
			holder.song = (TextView) view.findViewById(R.id.item_mymusic_song);
			holder.singer = (TextView) view
					.findViewById(R.id.item_mymusic_singer);
			holder.duration = (TextView) view
					.findViewById(R.id.item_mymusic_duration);
			holder.position = (TextView) view
					.findViewById(R.id.item_mymusic_postion);

			view.setTag(holder);
		} else {
			holder = (ViewHolder) view.getTag();
		}
		// 给控件赋值
		String string_song = list.get(i).getSong();
		if (string_song.length() >= 5
				&& string_song.substring(string_song.length() - 4,
						string_song.length()).equals(".mp3")) {
			holder.song.setText(string_song.substring(0,
					string_song.length() - 4).trim());
		} else {
			holder.song.setText(string_song.trim());
		}

		holder.singer.setText(list.get(i).getSinger().toString().trim());
		// 时间转换为时分秒
		int duration = list.get(i).getDuration();
		String time = MusicUtils.formatTime(duration);
		holder.duration.setText(time);

		return view;
	}

	class ViewHolder {
		TextView song;// 歌曲名
		TextView singer;// 歌手
		TextView duration;// 时长
		TextView position;// 序号
	}

}

adapter里面的列表项布局代码如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/item_mymusic_postion"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_alignBottom="@+id/item_mymusic_singer"
        android:layout_gravity="center_vertical"
        android:gravity="center"
        android:layout_margin="10dp"
        android:text="1"
        android:textSize="18sp" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="60dp">

        <TextView
            android:id="@+id/item_mymusic_song"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:ellipsize="end"
            android:maxLines="1"
            android:layout_marginRight="10dp"
            android:layout_marginTop="5dp"
            android:text="歌曲名"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/item_mymusic_singer"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_toLeftOf="@+id/item_mymusic_duration"
            android:gravity="bottom"
            android:text="歌手"
            android:ellipsize="end"
            android:maxLines="1"
            android:layout_marginBottom="5dp"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/item_mymusic_duration"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:gravity="bottom"
            android:layout_marginRight="5dp"
            android:layout_marginBottom="5dp"
            android:text="歌曲时间"
            android:textSize="16sp" />

    </RelativeLayout>


</LinearLayout>

然后在Listview所在的activity里,调用工具类获取音乐集合,构造适配器,给Listview设置适配器,即可在Listview中显示本地所有的音乐啦,关键代码就三行,如下

List<Song> list = MusicUtils.getMusicData(MainActivity.this);
MyAdapter adapter = new MyAdapter(MainActivity.this, list);
listview.setAdapter(adapter);

好了,到现在为止,你已经实现了,显示手机里所有的音乐,但是还不能播放,怎么播放,接着往下看

2.音乐的播放与控制

实现音乐播放,需要用到的类为MediaPlayer,为了方便,封装一个播放音乐的方法,如下

private void musicplay(int position) {
        try {
            mplayer.reset();
            mplayer.setDataSource(list.get(position).getPath());
            mplayer.prepare();
            mplayer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

传入的position为,播放的音乐的位置,即序号。

然后给listview设置点击事件

listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                musicplay(currentposition);
            }
        });

这样我们只是实现了简单的播放,点击Listview对应的条目,即可播放对应的音乐

我们下一步就是实现,音乐播放的控制,即暂停,下一曲,上一曲的实现

首先是暂停,在播放按钮的点击时间中,我们通常的需求是这样的,如果当前音乐正在播放,那么点击,暂停音乐,再点击,即可再次接着上次的继续播放,所以在播放按钮的点击事件中,需要根据不同情况处理,同时为了直观,需要准备两张图片,播放的时候一张,暂停的时候一张,播放按钮的点击事件如下

imageView_play.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                if (mplayer.isPlaying()) {
                    mplayer.pause();
                    imageview.clearAnimation();
                } else {
                    mplayer.start();
                    // thread = new Thread(new SeekBarThread());
                    // thread.start();
                    imageview.startAnimation(AnimationUtils.loadAnimation(
                            MainActivity.this, R.anim.imageview_rotate));
                }
            }
        });

由于为了界面体验良好,我这里还设置了,当音乐播放的时候,左侧图片的旋转效果,代码已经在上面的点击事件中,效果图如下

安卓开发个人小作品(3) - 多功能音乐播放器[通俗易懂]

左侧imageview的动画代码如下

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="20000"
    android:fromDegrees="0"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="-1"
    android:repeatMode="restart"
    android:toDegrees="360" />

扯了点其他的,下面来实现上一曲和下一曲的效果,我们也可以和播放一个,分别写一个对应的方法

上一曲方法代码如下

// 上一曲
    private void frontMusic() {
        currentposition--;
        if (currentposition < 0) {
            currentposition = list.size() - 1;
        }
        musicplay(currentposition);
    }

其中,currentposition是记录的当前音乐播放序号,这里有一点需要考虑的是,当前播放音乐的序号为0的时候,进行–操作之后那么会变成负数,所以,这里根据逻辑,处理为播放列表最后一曲,即设置序号为list.size()-1,形成一个环形。

相信你看了上一曲的方法,那么下一曲也很简单了,下一曲方法代码如下

// 下一曲
    private void nextMusic() {
        currentposition++;
        if (currentposition > list.size() - 1) {
            currentposition = 0;
        }
        musicplay(currentposition);
    }

同样我们也需要处理播放歌曲到最后一曲的时候,设置为播放列表第一首歌曲。

3.关联进度条seekbar,自定义seekbar

关联进度条的方法也很简单,这里将更新seekbar的方法重新开了一个线程,专门处理更新,代码如下

// 自定义的线程,用于下方seekbar的刷新
    class SeekBarThread implements Runnable {

        @Override
        public void run() {
            while (!ischanging && mplayer.isPlaying()) {
                // 将SeekBar位置设置到当前播放位置
                seekBar.setProgress(mplayer.getCurrentPosition());

                try {
                    // 每500毫秒更新一次位置
                    Thread.sleep(500);
                    // 播放进度

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

其中,ischanging用于判断当前的seekbar是否处于滑动状态,然后在音乐播放的地方,也就是刚才封装的musicplay方法中,更改为如下代码

private void musicplay(int position) {
        seekBar.setMax(list.get(position).getDuration());
        imageview.startAnimation(AnimationUtils.loadAnimation(
                MainActivity.this, R.anim.imageview_rotate));
        try {
            mplayer.reset();
            mplayer.setDataSource(list.get(position).getPath());
            mplayer.prepare();
            mplayer.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
        thread = new Thread(new SeekBarThread());
        thread.start();
    }

当然,不要忘了先设置seekbar的最大刻度值,也就是上面代码中setMax方法。

至此,你的音乐播放就已经和seekbar进度条关联起来了,但是你可能会发现系统默认的进度条很丑,不符合你的审美,那么我们就需要更改seekbar的样式,也就是自定义seekbar。

自定义seekbar,需要在布局中设置progressDrawable和thumb,分别对应进度条的背景和进度条的指示小图标,我这里进度条的背景采用的是drawable,代码如下

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:id="@+id/background">
        <shape>
            <solid 
                android:color="#DCDCDC"/>
        </shape>
    </item>
    <item android:id="@+id/secondaryProgress">
        <clip>
            <shape>
                <solid android:color="@color/blue" />
            </shape>
        </clip>
    </item>
    <item android:id="@+id/progress">
        <clip>
            <shape>
                <solid android:color="@color/blue" />
            </shape>
        </clip>
    </item>

</layer-list>

而thumb,我这里使用的就是一张图片,可以在我的项目源代码中找到,图片长下面这个样子

安卓开发个人小作品(3) - 多功能音乐播放器[通俗易懂]

当然你也可以采用自己的图片,来实现炫酷的效果哦!

4.单曲循环,顺序播放,随机播放的实现

实现这个效果,首先我哦们定义一个变量,用于记录当前的播放类型是哪种,如下

// 用于判断当前的播放顺序,0->单曲循环,1->顺序播放,2->随机播放
private int play_style = 0;

然后在我们的更改播放类型的按钮点击事件中,更改它的值,点击事件代码如下

imageview_playstyle.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                play_style++;
                if (play_style > 2) {
                    play_style = 0;
                }

                switch (play_style) {
                    case 0:
                        imageview_playstyle.setImageResource(R.mipmap.cicle);
                        Toast.makeText(MainActivity.this, "单曲循环",
                                Toast.LENGTH_SHORT).show();
                        break;
                    case 1:
                        imageview_playstyle.setImageResource(R.mipmap.ordered);
                        Toast.makeText(MainActivity.this, "顺序播放",
                                Toast.LENGTH_SHORT).show();
                        break;
                    case 2:
                        imageview_playstyle.setImageResource(R.mipmap.unordered);
                        Toast.makeText(MainActivity.this, "随机播放",
                                Toast.LENGTH_SHORT).show();
                        break;

                }
            }
        });

逻辑比较简单,应该都能看懂,然后就是怎么根据这个变量来实现对应的效果,核心方法就是MediaPLayer的setOnCompeleteListener,代码如下

// 监听mediaplayer播放完毕时调用
        mplayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {

            @Override
            public void onCompletion(MediaPlayer mp) {
                // TODO Auto-generated method stub
                switch (play_style) {
                    case 0:
                        musicplay(currentposition);
                        break;
                    case 1:
                        nextMusic();
                        break;
                    case 2:
                        random_nextMusic();
                        break;
                    default:

                        break;
                }
            }
        });

下一曲的代码上面已经给出了,下面是随机播放下一曲的代码,思想很简单,就是生成一个随机数,再设置为currentpositon,然后调用musicplay方法即可

// 随机播放下一曲
    private void random_nextMusic() {
        currentposition = currentposition + random.nextInt(list.size() - 1);
        currentposition %= list.size();
        musicplay(currentposition);
    }

5.设置喜爱音乐

喜爱音乐的设置,我这里处理的比较简单, 当长按列表项的时候,弹出对话框,用于设置喜爱音乐,效果如下

安卓开发个人小作品(3) - 多功能音乐播放器[通俗易懂]

然后,用sharepreference记录下喜爱音乐的序号值,当要播放喜爱音乐的时候,直接取到该序号值,然后调用musicplay方法播放序号值对应的音乐即可。主要就是sharepreference的使用,代码很简单,就不贴了

6.播放列表背景图设置与保存

设置播放列表背景也就是调用一下,listview.setBackground即可,但是我们如果不进行保存的话,下次进入APP的时候,背景图可能又恢复为初始的,那么我们就需要保存列表ode背景图,这里也采用sharepreference来保存,首先用Base64将图片转换为String,然后保存起来,下次进入APP的时候,再取出来,用Base64将String转为drawable对象,在设置上去即可。相关代码如下。

// 使用sharedPreferences保存listview背景图片
    private void saveDrawable(Drawable drawable) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        Bitmap bitmap = bitmapDrawable.getBitmap();
        // Bitmap bitmap = BitmapFactory.decodeResource(getResources(), id);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
        String imageBase64 = new String(Base64.encodeToString(
                baos.toByteArray(), Base64.DEFAULT));
        editor.putString("listbg", imageBase64);
        editor.commit();
    }

    // 加载用sharedPreferences保存的图片
    private Drawable loadDrawable() {
        String temp = sharedPreferences.getString("listbg", "");
        ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(
                temp.getBytes(), Base64.DEFAULT));
        return Drawable.createFromStream(bais, "");
    }

7.实现APP主题换肤的功能

实现主题效果,有很多种方法,我这里采用的是自定义属性的方法,首先我们在values下新建一个文件attrs,内容如下

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="theme_color" format="color" />
    <attr name="popupwindow_bg" format="reference"/>
    <attr name="dialogactivity_bg" format="reference"/>
    <attr name="btn_submit_bg" format="reference"/>
    <attr name="seekbar_progress_bg" format="reference"/>
    <attr name="play_image" format="reference" />
    <attr name="next_image" format="reference" />
    <attr name="front_image" format="reference" />
    <attr name="thumb_image" format="reference" />
    <attr name="indicate_image" format="reference" />
</resources>

这里每一个attr属性代表了哪些内容需要根据主题不同而更换,比如popupwindow_bg,即弹出窗口的背景色等等,然后在styles文件文件中指定各个主题下,这些值分别对应哪个具体的值,styles中相关代码如下

<style name="Theme_blue">
        <item name="theme_color">@color/blue</item>
        <item name="popupwindow_bg">@drawable/popupwindow_bg</item>
        <item name="dialogactivity_bg">@drawable/dialogactivity_bg</item>
        <item name="btn_submit_bg">@drawable/btn_submit_bg</item>
        <item name="seekbar_progress_bg">@drawable/seekbar_progress_bg</item>
        <item name="play_image">@mipmap/play</item>
        <item name="next_image">@mipmap/next</item>
        <item name="front_image">@mipmap/front</item>
        <item name="thumb_image">@mipmap/seekbar_thumb</item>
        <item name="indicate_image">@mipmap/play_small</item>
    </style>

    <style name="Theme_purple">
        <item name="theme_color">@color/purple</item>
        <item name="popupwindow_bg">@drawable/popupwindow_bg_purple</item>
        <item name="dialogactivity_bg">@drawable/dialogactivity_bg_purple</item>
        <item name="btn_submit_bg">@drawable/btn_submit_bg_purple</item>
        <item name="seekbar_progress_bg">@drawable/seekbar_progress_bg_purple</item>
        <item name="play_image">@mipmap/play_purple</item>
        <item name="next_image">@mipmap/next_purple</item>
        <item name="front_image">@mipmap/front_purple</item>
        <item name="thumb_image">@mipmap/seekbar_thumb_purple</item>
        <item name="indicate_image">@mipmap/play_small_purple</item>
    </style>

    <style name="Theme_green">
        <item name="theme_color">@color/green</item>
        <item name="popupwindow_bg">@drawable/popupwindow_bg_green</item>
        <item name="dialogactivity_bg">@drawable/dialogactivity_bg_green</item>
        <item name="btn_submit_bg">@drawable/btn_submit_bg_green</item>
        <item name="seekbar_progress_bg">@drawable/seekbar_progress_bg_green</item>
        <item name="play_image">@mipmap/play_green</item>
        <item name="next_image">@mipmap/next_green</item>
        <item name="front_image">@mipmap/front_green</item>
        <item name="thumb_image">@mipmap/seekbar_thumb_green</item>
        <item name="indicate_image">@mipmap/play_small_green</item>
    </style>

    <style name="Theme_red">
        <item name="theme_color">@color/red</item>
        <item name="popupwindow_bg">@drawable/popupwindow_bg_red</item>
        <item name="dialogactivity_bg">@drawable/dialogactivity_bg_red</item>
        <item name="btn_submit_bg">@drawable/btn_submit_bg_red</item>
        <item name="seekbar_progress_bg">@drawable/seekbar_progress_bg_red</item>
        <item name="play_image">@mipmap/play_red</item>
        <item name="next_image">@mipmap/next_red</item>
        <item name="front_image">@mipmap/front_red</item>
        <item name="thumb_image">@mipmap/seekbar_thumb_red</item>
        <item name="indicate_image">@mipmap/play_small_red</item>
    </style>

可以很清楚的看到,我设置了四个主题,每个主题中,我都对attrs中定义的属性进行了具体的赋值,然后怎么使用呢,举个例子,比如我现在需要让popupwindow的背景色随主题改变而更换,那么在popupwindow的布局中,设置其background属性为如下即可

android:background="?attr/popupwindow_bg"

其他属性的使用方法同理,然后我们如何来让用户设置主题呢,可以写一个dialog,也可popupwindow,不过我这里为了学习一下样式为dialog的activity,便采用了这种方式,最后效果如下

安卓开发个人小作品(3) - 多功能音乐播放器[通俗易懂]

看上去就像一个dialog,其实是一个activity,然后在这里根据用户的选择,来设置不同的主题,然后拿到主题的类型之后,在代码中根据这个值去判断应该显示哪个主题,相关代码如下

// 主题设置
string_theme = sharedPreferences.getString("theme_select", "blue");
if (string_theme.equals("blue")) {
      setTheme(R.style.Theme_blue);
} else if (string_theme.equals("purple")) {
      setTheme(R.style.Theme_purple);
} else if (string_theme.equals("green")) {
      setTheme(R.style.Theme_green);
} else {
      setTheme(R.style.Theme_red);
}
setContentView(R.layout.activity_main);

记住一定要在setContentView方法之前调用,具体细节各方面由于代码比较散,不方便贴,可以去源码里看我是怎么设置的,最终四个主题下的主界面效果如下

安卓开发个人小作品(3) - 多功能音乐播放器[通俗易懂]                   安卓开发个人小作品(3) - 多功能音乐播放器[通俗易懂]

安卓开发个人小作品(3) - 多功能音乐播放器[通俗易懂]                   安卓开发个人小作品(3) - 多功能音乐播放器[通俗易懂]

当然这个APP里,还有很多其他的细节,诸如,控制当前播放的列表项为不同颜色,顶部显示歌曲名字的彩色TextView等,这些可以直接去看源码,实现的方法也不难,欢迎访问源码!!

源码下载

源码下载

由于考虑到大家可能没有积分,我把源码重新传到了百度云,这样大家可以免费下载学习,链接和提取码如下:

链接: https://pan.baidu.com/s/1KNxJvsE6XTIi3JkEBgCNgw 提取码: 4xhi 

任何问题,也可以加我vx交流:hqq_0711

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/153231.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • linux tail 命令查看日志「建议收藏」

    linux tail 命令查看日志「建议收藏」#输出文件末尾行(默认10行),当文件增长时,输出后续添加的行(-f即–follow=file.log不会回传结束信号,除非我们去自行去中断它)tail-ffile.log#输出文件末尾包含关键字的行,当文件增长时,输出后续添加的行(-f即–follow=file.log不会回传结束信号,除非我们去自行去…

  • pycharm安装教程2020.3.4_pycharm安装后无解释器

    pycharm安装教程2020.3.4_pycharm安装后无解释器第一步安装解释器,第二步安装pycharm1第一步安装解释器1.1什么是解释器:??就是将Python程序翻译成为计算机可以识别的01代码1.2安装解释器:解释器安装地址:https://www.python.org/downloads/release/python-372根据自己的操作系统安装适配的解释器:这里以Windows为例注意安装的时候我们需要需注意吧解释器添加到环境变量里面双击开始安装勾选addpythontopath,如果安装的时候没有勾选,请安装结束以后按

  • 毕业设计之Qt播放器[通俗易懂]

    毕业设计之Qt播放器[通俗易懂]一、功能介绍1、有拖拉功能,将视频直接拖进,播放器即可播放视频2、可以有加密视频,将放视频的文件夹加密3、有定时开关机的功能4、有网上直接看视频的功能5、有打开本地视频的功能6、可以浏览照片7、可以播放歌曲8、有最新电影推荐功能9、播放列表10、1499小游戏,在线玩二、llplayer  以完成功能1、正常播放ok2、文件夹打开ok,

  • 毕业两年

    又到毕业季,去年毕业一年,今年,毕业两年了,一年一度的“毕业N年”系列。今年经历了两件事,离职和成长。离职 去年8月份从百度离职了,北京来到杭州,加入现在这家创业公司,做乐器教育方向的,应用叫Finger。成长 技术。这个三两句话也说不清楚,最近一年忙于工作也没写博客了。从客观角度来看的话,更多关注工程的架构和可扩展性,也厌烦了重复性的工作,把重复性的逻辑都通过封装解耦出去,通过“

  • 正则表达式替换某个字符「建议收藏」

    正则表达式替换某个字符「建议收藏」需要匹配指定位置的某个字符示例:替换时间戳中的最后一个冒号为.号//原始字符串letstr="18:78:45:222"//匹配letreg=/^(.{5,8}):(.*)$/g//替换letresult=str.replace(reg,"$1*$2")希望有更好的方法,看官们留个言呗…

  • python获取图片并储存图片_python用户输入矩形的长和宽

    python获取图片并储存图片_python用户输入矩形的长和宽1、opencv2、imageio3、matplotlib4、scipy#coding:utf-8importcv2importimageiofromscipyimportmiscfromPILimportImagefrommatplotlibimportpyplotaspltimage_path=”./images/000011.jpg”#使用pillow读取图…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号