第十天 权重 系统管理员 2022-07-26 00:18 133阅读 0赞 \#\#day11\#\# \- 系统进程显示和隐藏 \- 创建进程管理设置页面:ProcessManagerSettingActivity \- 编写设置页面布局文件 \- 监听Checkbox的勾选事件,更新本地SharePreference // 根据本地记录,更新checkbox状态 boolean showSystem = mPrefs.getBoolean("show\_system\_process", true); if (showSystem) \{ cbShowSystem.setChecked(true); cbShowSystem.setText("显示系统进程"); \} else \{ cbShowSystem.setChecked(false); cbShowSystem.setText("不显示系统进程"); \} // 设置状态勾选监听 cbShowSystem.setOnCheckedChangeListener(new OnCheckedChangeListener() \{ @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) \{ if (isChecked) \{ cbShowSystem.setText("显示系统进程"); mPrefs.edit().putBoolean("show\_system\_process", true).commit(); \} else \{ cbShowSystem.setText("不显示系统进程"); mPrefs.edit().putBoolean("show\_system\_process", false) .commit(); \} \} \}); \- 根据sp记录的是否显示系统进程,更新listview的显示个数 @Override public int getCount() \{ // 通过判断是否显示系统进程,更新list的数量 boolean showSystem = mPrefs.getBoolean("show\_system\_process", true); if (showSystem) \{ return 1 + mUserProcessList.size() + 1 + mSystemProcessList.size(); \} else \{ return 1 + mUserProcessList.size(); \} \} \- 保证勾选框改变后,listview可以立即刷新 public void setting(View view) \{ startActivityForResult(new Intent(this, ProcessManagerSettingActivity.class), 0); \} @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) \{ // 当从设置页面回跳回来之后,刷新listview mAdapter.notifyDataSetChanged(); \} \- 锁屏清理 \- 演示金山进程管理效果 \- 后台启动服务,监听广播 //判断锁屏清理的广播是否正在运行 boolean serviceRunning = ServiceStatusUtils.isServiceRunning( "com.itheima.mobilesafeteach.service.AutoKillService", this); if (serviceRunning) \{ cbLockClear.setChecked(true); cbLockClear.setText("当前状态:锁屏清理已经开启"); \} else \{ cbLockClear.setChecked(false); cbLockClear.setText("当前状态:锁屏清理已经关闭"); \} cbLockClear.setOnCheckedChangeListener(new OnCheckedChangeListener() \{ @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) \{ Intent intent = new Intent(ProcessManagerSettingActivity.this, AutoKillService.class); if (isChecked) \{ // 启动锁屏清理的服务 startService(intent); cbLockClear.setText("当前状态:锁屏清理已经开启"); \} else \{ // 关闭锁屏清理的服务 stopService(intent); cbLockClear.setText("当前状态:锁屏清理已经关闭"); \} \} \}); \------------------------------------- /\*\* \* 锁屏清理进程的服务 \* \* @author Kevin \* \*/ public class AutoKillService extends Service \{ private InnerScreenOffReceiver mReceiver; @Override public IBinder onBind(Intent intent) \{ return null; \} @Override public void onCreate() \{ super.onCreate(); //监听屏幕关闭的广播, 注意,该广播只能在代码中注册,不能在清单文件中注册 mReceiver = new InnerScreenOffReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION\_SCREEN\_OFF); registerReceiver(mReceiver, filter); \} @Override public void onDestroy() \{ super.onDestroy(); unregisterReceiver(mReceiver); mReceiver = null; \} /\*\* \* 锁屏关闭的广播接收者 \* \* @author Kevin \* \*/ class InnerScreenOffReceiver extends BroadcastReceiver \{ @Override public void onReceive(Context context, Intent intent) \{ System.out.println("屏幕关闭..."); // 杀死后台所有运行的进程 ActivityManager am = (ActivityManager) getSystemService(ACTIVITY\_SERVICE); List<RunningAppProcessInfo> runningAppProcesses = am .getRunningAppProcesses(); for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses) \{ // 跳过手机卫士的服务 if (runningAppProcessInfo.processName.equals(ctx.getPackageName())) \{ return; \} am.killBackgroundProcesses(runningAppProcessInfo.processName); \} \} \} \} \- 定时器清理(介绍) // 在AutoKillService的onCreate中启动定时器,定时清理任务 mTimer = new Timer(); mTimer.schedule(new TimerTask() \{ @Override public void run() \{ System.out.println("5秒运行一次!"); \} \}, 0, 5000); @Override protected void onDestroy() \{ super.onDestroy(); mTimer.cancel(); mTimer = null; \} \- 桌面Widget(窗口小部件) \- widget介绍(Android, 瑞星,早期word) \- widget谷歌文档查看(API Guide->App Components->App Widget) \- widget开发流程 1. 在com.itheima.mobilesafe.receiver目录下创建MyWidget并且继承AppWidgetProvider 2. 在功能清单文件注册,参照文档 <receiver android:name=".receiver.MyWidget" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET\_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget\_info" /> </receiver> 3. 在res/xml/创建文件example\_appwidget\_info.xml拷贝文档内容 <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="294dp" android:minHeight="72dp"//能被调整的最小宽高,若大于minWidth minHeight 则忽略 android:updatePeriodMillis="86400000"//更新周期,毫秒,最短默认半小时 android:previewImage="@drawable/preview"//选择部件时 展示的图像,3.0以上使用,默认是ic\_launcher android:initialLayout="@layout/example\_appwidget"//布局文件 android:configure="com.example.android.ExampleAppWidgetConfigure"//添加widget之前,先跳转到配置的activity进行相关参数配置,这个我们暂时用不到 android:resizeMode="horizontal|vertical"//widget可以被拉伸的方向。horizontal表示可以水平拉伸,vertical表示可以竖直拉伸 android:widgetCategory="home\_screen|keyguard"//分别在屏幕主页和锁屏状态也能显示(4.2+系统才支持) android:initialKeyguardLayout="@layout/example\_keyguard"//锁屏状态显示的样式(4.2+系统才支持) > </appwidget-provider> 4. 精简example\_appwidget\_info.xml文件,最终结果: <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="294dp" android:minHeight="72dp" android:updatePeriodMillis="1800000" android:initialLayout="@layout/appwidget" > </appwidget-provider> 5. widget布局文件:appwidget.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout\_width="match\_parent" android:layout\_height="match\_parent" android:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout\_width="wrap\_content" android:layout\_height="wrap\_content" android:background="\#f00" android:text="我是widget,哈哈哈" android:textSize="30sp" /> </LinearLayout> \- 简单演示,高低版本对比 \- 仿照金山widget效果, apktool反编译,抄金山布局文件(业内抄袭成风) 1. 反编译金山apk 使用apktool,可以查看xml文件内容 apktool d xxx.apk 2. 在金山清单文件中查找 APPWIDGET\_UPDATE, 找到widget注册的代码 3. 拷贝金山widget的布局文件process\_widget\_provider.xml到自己的项目中 4. 从金山项目中拷贝相关资源文件,解决报错 5. 运行,查看效果 \- widget生命周期 /\*\* \* 窗口小部件widget \* \* @author Kevin \* \*/ public class MyWidget extends AppWidgetProvider \{ /\*\* \* widget的每次变化都会调用onReceive \*/ @Override public void onReceive(Context context, Intent intent) \{ super.onReceive(context, intent); System.out.println("MyWidget: onReceive"); \} /\*\* \* 当widget第一次被添加时,调用onEnable \*/ @Override public void onEnabled(Context context) \{ super.onEnabled(context); System.out.println("MyWidget: onEnabled"); \} /\*\* \* 当widget完全从桌面移除时,调用onDisabled \*/ @Override public void onDisabled(Context context) \{ super.onDisabled(context); System.out.println("MyWidget: onDisabled"); \} /\*\* \* 新增widget时,或者widget更新时,调用onUpdate \* 更新时间取决于xml中配置的时间,最短为半小时 \*/ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int\[\] appWidgetIds) \{ super.onUpdate(context, appWidgetManager, appWidgetIds); System.out.println("MyWidget: onUpdate"); \} /\*\* \* 删除widget时,调onDeleted \*/ @Override public void onDeleted(Context context, int\[\] appWidgetIds) \{ super.onDeleted(context, appWidgetIds); System.out.println("MyWidget: onDeleted"); \} /\*\* \* 当widget大小发生变化时,调用此方法 \*/ @Override public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) \{ System.out.println("MyWidget: onAppWidgetOptionsChanged"); \} \} \- 定时更新widget 问题: 我们需要通过widget实时显示当前进程数和可用内存,但widget最短也得半个小时才会更新一次, 如何才能间隔比较短的时间来及时更新? 查看金山日志: 当桌面有金山widget时, 金山会在后台启动service:ProcessService,并定时输出如下日志: 03-29 08:43:03.070: D/MoSecurity.ProcessService(275): updateWidget 该日志在锁屏状态下也一直输出. 解决办法: 后台启动service,UpdateWidgetService, 并在service中启动定时器来控制widget的更新 \- 更新widget方法 /\*\* \* 定时更新widget的service \* \* @author Kevin \* \*/ public class UpdateWidgetService extends Service \{ private Timer mTimer; private AppWidgetManager mAWM; @Override public IBinder onBind(Intent intent) \{ return null; \} @Override public void onCreate() \{ super.onCreate(); mAWM = AppWidgetManager.getInstance(this); // 启动定时器,每个5秒一更新 mTimer = new Timer(); mTimer.schedule(new TimerTask() \{ @Override public void run() \{ System.out.println("更新widget啦!"); updateWidget(); \} \}, 0, 5000); \} /\*\* \* 更新widget \*/ private void updateWidget() \{ // 初始化远程的view对象 RemoteViews views = new RemoteViews(getPackageName(), R.layout.process\_widget); views.setTextViewText(R.id.tv\_running\_processes, "正在运行的软件:" \+ ProcessInfoProvider.getRunningProcessNum(this)); views.setTextViewText( R.id.tv\_memory\_left, "可用内存:" \+ Formatter.formatFileSize(this, ProcessInfoProvider.getAvailMemory(this))); // 初始化组件 ComponentName provider = new ComponentName(this, MyWidget.class); // 更新widget mAWM.updateAppWidget(provider, views); \} @Override public void onDestroy() \{ super.onDestroy(); mTimer.cancel(); mTimer = null; \} \} \----------------------------- 启动和销毁service的时机 分析widget的声明周期,在onEnabled和onUpdate中启动服务, 在onDisabled中结束服务 \- 注意: APK安装在sd卡上,widget在窗口小部件列表里无法显示。 android:installLocation="preferExternal", 修改过来后,需要卸载,再去安装widget才生效; \- 点击事件处理 // 初始化延迟意图,pending是等待的意思 Intent intent = new Intent(this, HomeActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG\_UPDATE\_CURRENT); // 当点击widget布局时,跳转到主页面 views.setOnClickPendingIntent(R.id.ll\_root, pendingIntent); //当一键清理被点击是,发送广播,清理内存 Intent btnIntent = new Intent(); btnIntent.setAction("com.itheima.mobilesafeteach.KILL\_ALL"); PendingIntent btnPendingIntent = PendingIntent.getBroadcast(this, 0, btnIntent, PendingIntent.FLAG\_UPDATE\_CURRENT); views.setOnClickPendingIntent(R.id.btn\_clear, btnPendingIntent); \--------------------------- /\*\* \* 杀死后台进程的广播接受者 \* 清单文件中配置action="com.itheima.mobilesafeteach.KILL\_ALL" \* \* @author Kevin \* \*/ public class KillAllReceiver extends BroadcastReceiver \{ @Override public void onReceive(Context context, Intent intent) \{ System.out.println("kill all..."); // 杀死后台所有运行的进程 ProcessInfoProvider.killAll(context); \} \} \--------------------------- <receiver android:name=".receiver.KillAllReceiver" > <intent-filter> <action android:name="com.itheima.mobilesafeteach.KILL\_ALL" /> </intent-filter> </receiver> \- 做一个有情怀的程序员, 拒绝耗电! 当锁屏关闭时,停止widget定时器的更新 UpdateWidgetService: // 注册屏幕开启和关闭的广播接受者 mReceiver = new InnerScreenReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION\_SCREEN\_OFF); filter.addAction(Intent.ACTION\_SCREEN\_ON); registerReceiver(mReceiver, filter); /\*\* \* 屏幕关闭和开启的广播接收者 \* \* @author Kevin \* \*/ class InnerScreenReceiver extends BroadcastReceiver \{ @Override public void onReceive(Context context, Intent intent) \{ String action = intent.getAction(); if (Intent.ACTION\_SCREEN\_OFF.equals(action)) \{// 屏幕关闭 if (mTimer != null) \{ // 停止定时器 mTimer.cancel(); mTimer = null; \} \} else \{// 屏幕开启 startTimer(); \} \} \} \- 程序锁 \- 高级工具中添加程序锁入口 \- 新建程序锁页面 AppLockActivity \- 程序锁页面布局文件实现 activity\_app\_lock.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout\_width="match\_parent" android:layout\_height="match\_parent" android:orientation="vertical" > <LinearLayout android:layout\_width="match\_parent" android:layout\_height="wrap\_content" android:gravity="center" android:orientation="horizontal" > <TextView android:id="@+id/tv\_unlock" android:layout\_width="wrap\_content" android:layout\_height="wrap\_content" android:background="@drawable/tab\_left\_pressed" android:gravity="center" android:text="未加锁" android:textColor="\#fff" /> <TextView android:id="@+id/tv\_locked" android:layout\_width="wrap\_content" android:layout\_height="wrap\_content" android:background="@drawable/tab\_right\_default" android:gravity="center" android:text="已加锁" android:textColor="\#fff" /> </LinearLayout> <LinearLayout android:id="@+id/ll\_unlock" android:layout\_width="match\_parent" android:layout\_height="match\_parent" android:orientation="vertical" > <TextView android:layout\_width="wrap\_content" android:layout\_height="wrap\_content" android:text="未加锁软件:x个" android:textColor="\#000" /> <ListView android:id="@+id/lv\_unlock" android:layout\_width="match\_parent" android:layout\_height="match\_parent" /> </LinearLayout> <LinearLayout android:id="@+id/ll\_locked" android:layout\_width="match\_parent" android:layout\_height="match\_parent" android:orientation="vertical" android:visibility="gone" > <TextView android:layout\_width="wrap\_content" android:layout\_height="wrap\_content" android:text="已加锁软件:x个" android:textColor="\#000" /> <ListView android:id="@+id/lv\_locked" android:layout\_width="match\_parent" android:layout\_height="match\_parent" /> </LinearLayout> </LinearLayout> \- 点击标签切换页面 @Override public void onClick(View v) \{ switch (v.getId()) \{ case R.id.tv\_unlock:// 展示未加锁页面,隐藏已加锁页面 llLocked.setVisibility(View.GONE); llUnlock.setVisibility(View.VISIBLE); tvUnlock.setBackgroundResource(R.drawable.tab\_left\_pressed); tvLocked.setBackgroundResource(R.drawable.tab\_right\_default); break; case R.id.tv\_locked:// 展示已加锁页面,隐藏未加锁页面 llUnlock.setVisibility(View.GONE); llLocked.setVisibility(View.VISIBLE); tvUnlock.setBackgroundResource(R.drawable.tab\_left\_default); tvLocked.setBackgroundResource(R.drawable.tab\_right\_pressed); break; default: break; \} \} \- 应用列表信息展现(展现全部应用列表数据) \- 使用数据库保存已加锁的软件 AppLockOpenHelper.java // 创建表, 两个字段,\_id, packagename(应用包名) db.execSQL("create table applock (\_id integer primary key autoincrement, packagename varchar(50))"); \---------------------------------- AppLockDao.java(逻辑和黑名单列表类似) /\*\* \* 增加程序锁应用 \*/ public void add(String packageName) \{ SQLiteDatabase db = mHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("packagename", packageName); db.insert("applock", null, values); db.close(); \} /\*\* \* 删除程序锁应用 \* \* @param number \*/ public void delete(String packageName) \{ SQLiteDatabase db = mHelper.getWritableDatabase(); db.delete("applock", "packagename=?", new String\[\] \{ packageName \}); db.close(); \} /\*\* \* 查找程序锁应用 \* \* @param number \* @return \*/ public boolean find(String packageName) \{ SQLiteDatabase db = mHelper.getWritableDatabase(); Cursor cursor = db.query("applock", null, "packagename=?", new String\[\] \{ packageName \}, null, null, null); boolean result = false; if (cursor.moveToFirst()) \{ result = true; \} cursor.close(); db.close(); return result; \} /\*\* \* 查找已加锁列表 \* \* @return \*/ public ArrayList<String> findAll() \{ SQLiteDatabase db = mHelper.getWritableDatabase(); Cursor cursor = db.query("applock", new String\[\] \{ "packagename" \}, null, null, null, null, null); ArrayList<String> list = new ArrayList<String>(); while (cursor.moveToNext()) \{ String packageName = cursor.getString(0); list.add(packageName); \} cursor.close(); db.close(); return list; \} \- 监听list item点击事件,向数据库添加一些数据 lvUnLock.setOnItemClickListener(new OnItemClickListener() \{ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) \{ AppInfo info = mUnlockList.get(position); mDao.add(info.packageName); \} \}); \- 已加锁和未加锁数据设置 private ArrayList<AppInfo> mLockedList;// 已加锁列表集合 private ArrayList<AppInfo> mUnlockList;// 未加锁列表集合 private Handler mHandler = new Handler() \{ public void handleMessage(android.os.Message msg) \{ // 设置未加锁数据 mUnlockAdapter = new AppLockAdapter(false); lvUnLock.setAdapter(mUnlockAdapter); // 设置已加锁数据 mLockedAdapter = new AppLockAdapter(true); lvLocked.setAdapter(mLockedAdapter); \}; \}; /\*\* \* 初始化应用列表数据 \*/ private void initData() \{ new Thread() \{ @Override public void run() \{ mList = AppInfoProvider.getAppInfos(AppLockActivity.this); mLockedList = new ArrayList<AppInfo>(); mUnlockList = new ArrayList<AppInfo>(); for (AppInfo info : mList) \{ boolean isLocked = mDao.find(info.packageName); if (isLocked) \{ mLockedList.add(info); \} else \{ mUnlockList.add(info); \} \} mHandler.sendEmptyMessage(0); \} \}.start(); \} \- 界面效果完善 点击锁子图标后, 实现加锁和去加锁的逻辑, 界面跟着更新 class AppLockAdapter extends BaseAdapter \{ private boolean isLocked;//true表示已加锁数据 public AppLockAdapter(boolean isLocked) \{ this.isLocked = isLocked; \} @Override public int getCount() \{ if (isLocked) \{ return mLockedList.size(); \} else \{ return mUnlockList.size(); \} \} @Override public AppInfo getItem(int position) \{ if (isLocked) \{ return mLockedList.get(position); \} else \{ return mUnlockList.get(position); \} \} @Override public long getItemId(int position) \{ return position; \} @Override public View getView(final int position, View convertView, ViewGroup parent) \{ ViewHolder holder; if (convertView == null) \{ convertView = View.inflate(AppLockActivity.this, R.layout.list\_applock\_item, null); holder = new ViewHolder(); holder.ivIcon = (ImageView) convertView .findViewById(R.id.iv\_icon); holder.tvName = (TextView) convertView .findViewById(R.id.tv\_name); holder.ivLock = (ImageView) convertView .findViewById(R.id.iv\_lock); convertView.setTag(holder); \} else \{ holder = (ViewHolder) convertView.getTag(); \} final AppInfo info = getItem(position); holder.ivIcon.setImageDrawable(info.icon); holder.tvName.setText(info.name); if(isLocked) \{ holder.ivLock.setImageResource(R.drawable.unlock); \}else \{ holder.ivLock.setImageResource(R.drawable.lock); \} holder.ivLock.setOnClickListener(new OnClickListener() \{ @Override public void onClick(View v) \{ if (isLocked) \{ mDao.delete(info.packageName);// 从数据库删除记录 mLockedList.remove(info);// 从已加锁集合删除元素 mUnlockList.add(info);// 给未加锁集合添加元素 \} else \{ mDao.add(info.packageName);// 向数据库添加记录 mLockedList.add(info);// 给已加锁集合添加元素 mUnlockList.remove(info);// 从未加锁集合删除元素 \} // 刷新listview mLockedAdapter.notifyDataSetChanged(); mUnlockAdapter.notifyDataSetChanged(); \} \}); return convertView; \} \} \- 更新已加锁/未加锁数量 /\*\* \* 更新已加锁和未加锁数量 \*/ private void updateAppNum() \{ tvUnLockNum.setText("未加锁软件:" + mUnlockList.size() + "个"); tvLockedNum.setText("已加锁软件:" + mLockedList.size() + "个"); \} // 每次刷新listview前都会调用getCount方法,可以在这里更新数量 @Override public int getCount() \{ updateAppNum(); if (isLocked) \{ return mLockedList.size(); \} else \{ return mUnlockList.size(); \} \} \- 动画实现 \- 解决动画移动问题 导致的原因,动画没有开始播放,界面就刷新了。 动画播放需要时间的,动画没有播就变成了新的View对象。就播了新的View对象, 让动画播放完后,再去更新页面; public AppLockAdapter(boolean isLocked) \{ this.isLocked = isLocked; // 右移 mLockAnim = new TranslateAnimation(Animation.RELATIVE\_TO\_SELF, 0f, Animation.RELATIVE\_TO\_SELF, 1f, Animation.RELATIVE\_TO\_SELF, 0, Animation.RELATIVE\_TO\_SELF, 0); mLockAnim.setDuration(500); // 左移 mUnLockAnim = new TranslateAnimation(Animation.RELATIVE\_TO\_SELF, 0f, Animation.RELATIVE\_TO\_SELF, -1f, Animation.RELATIVE\_TO\_SELF, 0, Animation.RELATIVE\_TO\_SELF, 0); mUnLockAnim.setDuration(500); \} holder.ivLock.setOnClickListener(new OnClickListener() \{ @Override public void onClick(View v) \{ if (isLocked) \{ view.startAnimation(mUnLockAnim); mUnLockAnim .setAnimationListener(new AnimationListener() \{ @Override public void onAnimationStart( Animation animation) \{ \} @Override public void onAnimationRepeat( Animation animation) \{ \} //监听动画结束事件 @Override public void onAnimationEnd( Animation animation) \{ mDao.delete(info.packageName);// 从数据库删除记录 mLockedList.remove(info);// 从已加锁集合删除元素 mUnlockList.add(info);// 给未加锁集合添加元素 // 刷新listview mLockedAdapter.notifyDataSetChanged(); mUnlockAdapter.notifyDataSetChanged(); \} \}); \} else \{ view.startAnimation(mLockAnim); mLockAnim.setAnimationListener(new AnimationListener() \{ @Override public void onAnimationStart(Animation animation) \{ \} @Override public void onAnimationRepeat(Animation animation) \{ \} //监听动画结束事件 @Override public void onAnimationEnd(Animation animation) \{ mDao.add(info.packageName);// 向数据库添加记录 mLockedList.add(info);// 给已加锁集合添加元素 mUnlockList.remove(info);// 从未加锁集合删除元素 // 刷新listview mLockedAdapter.notifyDataSetChanged(); mUnlockAdapter.notifyDataSetChanged(); \} \}); \} \} \});
相关 css权重(css权重优先级) 什么是权重,权数? 在数学方面,表示某个数据出现的频率、次数叫权重或者权数。 ![css权重(css权重优先级)\_css权重(css权重优先级)][css_css_c 待我称王封你为后i/ 2023年09月26日 13:16/ 0 赞/ 39 阅读
相关 第十天 权重 \\day11\\ \- 系统进程显示和隐藏 \- 创建进程管理设置页面:ProcessManagerSettingActivity \- 编写设置页面 系统管理员/ 2022年07月26日 00:18/ 0 赞/ 134 阅读
相关 EasyMall第十天 8.20 Coookie回顾:本质是用response设置cookie的头,Set-Cookie:值。 一旦设置了这个响应头,下次访问服务器时,将在请求头中带 小灰灰/ 2022年06月09日 09:17/ 0 赞/ 271 阅读
相关 QT第十天 QFileSystemModel 使用QFileSystemModel作为数据模型,QTreeView,QListView和QTableView为主要组件 在Tree Bertha 。/ 2022年04月11日 11:42/ 0 赞/ 341 阅读
相关 Qt第十五天 自定义对话框及其调用 QWDialogSize的创建 qwdialogsize.h ifndef QWDIALOGSIZE_H define QW 以你之姓@/ 2022年04月08日 12:41/ 0 赞/ 301 阅读
相关 Qt第十一天 QStringListModel的使用 采用QStringListModel作为数据模型,QListView组件作为视图组件 演示了QStringListModel和 痛定思痛。/ 2022年04月08日 09:22/ 0 赞/ 280 阅读
相关 Qt第十八天 Graphics View绘图程序实例 \\可以创建矩形,椭圆,圆,三角形,梯形,直线,文字等基本图形项 每个图形项可以被选择,拖动,放缩,旋转 图形项的前置和后 逃离我推掉我的手/ 2022年04月04日 11:47/ 0 赞/ 390 阅读
相关 Qt第十七天 QGraphicsView程序基本结构和功能实现 mainwindow.h ifndef MAINWINDOW_H define MAINWINDOW_ 快来打我*/ 2022年04月04日 09:18/ 0 赞/ 328 阅读
相关 Qt第十六天’ 坐标变换 坐标平移 坐标旋转 坐标缩放 状态的保存和恢复 widget.h ifndef WIDGET_H define WIDGET 快来打我*/ 2022年04月04日 03:07/ 0 赞/ 306 阅读
相关 第十四天 今日所得 模块 import from...import... 循环导入 相对导入 绝对导入 软件开发目录规范 模块 模块:是 拼搏现实的明天。/ 2021年11月11日 09:10/ 0 赞/ 373 阅读
还没有评论,来说两句吧...