JavaGUI:多功能计算器(五)--Swing实现双语数据包+菜单切换(完整源码)

news2025/1/13 10:26:34

JavaGUI:多功能计算器(五)–Swing实现双语数据包+菜单切换(完整源码)

【背景提示】

“软件国际化”就是实现多种语言显示切换。
1.在前端网页上,可通过探测本地化语言环境实现自动切换;
2.在操作系统如Win10中,有各种显示语言包,可以下载/安装/卸载;
3.在应用程序App中,有专门的语言数据包,如中文/日文语言包等。

一、简单实现语言包:

在java的SwingGUI中,可以方便地实现双语悬停提示,但要实现语言包功能,难点就是要设计好语言包的格式。

本文的方法是:

  1. 使用Java特有的二维可变长数组(见程序前端的LANG[ ][ ]);
  2. 将GUI界面需显示的字符串进行分组,如按键组“pkeys”和菜单组“menu”;
  3. 字串分组里再按 “组信息+英文组+中文组”的顺序排列;
  4. 各分组顺序可任意排列,保持编辑修改的灵活性;

实现的功能为:

  1. 保留前文v0.40版本的鼠标悬停双语互提示功能(由iLang判别);
  2. 菜单切换中英文界面;切换后可同时看到两个窗口,但焦点在最后启动的窗口;关闭焦点窗口会同时关闭前导窗口,而关闭前导窗口不会关闭焦点窗口;
  3. 程序后面的命令执行部分仍然使用英文命令,中文命令由cmdIndex()方法实现自动转换;(详情参见后面完整源码)

二、完整源码:

(本源码版本为v0.41;后面的按键和菜单命令执行部分与前文v0.34基本相同)

//TODO v0.41;20230101w0;JavaSwing实现多语言菜单切换@多功能计算器;(同时保留双语悬停提示)
//文章标签: java gui awt swing eclipse
//版本说明:
//v0.41;20230101w0;JavaSwing实现多语言数据包@多功能计算器;双语菜单切换+悬停提示,创新版;
//v0.40;20221230;JavaSwing实现双语悬停提示@多功能计算器;(AWT2Swing直接升级版)


package calculator;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class Calculate
{
    //v0.34;20221005;总体布局;完整版3位版本号;简易版仅需1位版本号;   	
	//v0.40;20221230(AWT2Swing直接升级版);
	//计算变量:
	private double 		num1,num2,mem;					//操作数1/2,中间记忆mem,均为double;
	private boolean 	isNum;							//数字拼接标志位,转存后失效;
	private String 		Oper;							//二元计算操作符,依赖"="计算;
	//显示变量:
	private JTextArea 	tRecord;						//操作记录;多行可编辑复制;用CR按键清空;
	private JTextField 	tResult;						//计算结果;单行可退格,由C按键复制后清空;
	//主框架:
	private JFrame 		frame;
	private int 		wFrame;
	private int 		hFrame;
	private int 		iLang=0;						//语言代码:默认0英文,,1中文;2俄文,3韩文,4日文;
	//v0.41;20230101;定义窗口语言数据包;
	private final String[][] LANG = {
		{"language","1","0"},
		{"English","Chinese","Russian"},				//iLang=0,1,2;
		{"英语","汉语","俄语"},
		{"about","1","100","70"},
		{"About","Auther: yy-2020."},
		{"关于DbY","作者: yy-2020."},
		{"frame","1","590","270","res/yy-2020.png"},	//主框架frame,大小及图标文件;
		{"Calculator V0.41"},
		{"计算器DbY v0.41"},
		{"textshow","1","5","20"},						//文本显示,默认5行25列;
		{"RecordArea\n","ResultField"},
		{"操作记录区\n","计算结果"},
		{"pkeys","7","8"},								//按键板,默认7行8列;
		{"temp"	,"f(x)"	,"n!"	,"("	,"d"	,"e"	,"f"	,"x^y"},
		{"tone"	,"log10","cbrt"	,")"	,"a"	,"b"	,"c"	,"%"},	
		{"tune"	,"tan"	,"sqrt"	,"MC"	,"7"	,"8"	,"9"	,"/"}, 
		{"oct"	,"cos"	,"x^3"	,"M"	,"4"	,"5"	,"6"	,"*"},
		{"sus"	,"sin"	,"x^2"	,"E"	,"1"	,"2"	,"3"	,"-"}, 
		{"chrd"	,"rand"	,"1/x"	,"PI"	,"0"	,"."	,"-/+"	,"+"},
		{"midi"	,"time"	,"dec"	,"hex"	,"CR"	,"C"	,"BS"	,"="},
		{"速度"	,"函数"	,"阶乘"	,"("	,"d"	,"e"	,"f"	,"乘方"},
		{"音色"	,"对数10"	,"立方根"	,")"	,"a"	,"b"	,"c"	,"取余"},	
		{"变调"	,"正切"	,"平方根"	,"清存储"	,"7"	,"8"	,"9"	,"除"}, 
		{"八度"	,"余弦"	,"立方"	,"存储"	,"4"	,"5"	,"6"	,"乘"},
		{"延音"	,"正弦"	,"平方"	,"欧拉数"	,"1"	,"2"	,"3"	,"减"}, 
		{"和弦"	,"随机数"	,"倒数"	,"圆周率"	,"0"	,"."	,"取负"	,"加"},
		{"编曲"	,"时间"	,"10进制"	,"16进制"	,"清记录"	,"清结果"	,"退格"	,"="},
		{"menu","5","0"},								//菜单定义;
		{"File","Open","Save","saveTo","Exit"},
		{"Option","Typical","Personal","Multifunc","Default","Set"},
		{"Help","tTip","tShow","About","Example","Constant","Formula"},
		{"eXtends","Music","Calendar","Weather","Health"},
		{"Language","English","Chinese"},
		{"文件","打开","保存","另存","退出"},				
		{"选项","典型","个性","多功能","默认","多选"},			
		{"帮助","提示","显示","关于","示例","常数","公式"},			
		{"扩展","音乐","日历","天气","健康"},	
		{"语言","英文","中文"},		
	};
	
	//v0.41;20230103;语言数据包LANG[][]串组分类索引方法;类串cStr;返回类串索引号i;
	private int classIndex(String cStr,String[][] Lang) {		
		for(int i=0;i<Lang.length;i++) {
			if(Lang[i][0]==cStr) return i;				//返回类串索引号i;
		}return -1;										//未找到匹配项,返回异常;								
	}
	//v0.41;20230108;英语命令回归索引方法;为新增的双语串组LANG[][]专门改写的版本;
	private String cmdIndex(String str,String cStr,String[][] Lang) {
		int s = classIndex(cStr,Lang); 					//本类起始行号s@Lang[][];
		int nRow = Integer.parseInt(Lang[s+0][1]);		//本类行数nRow@Lang[][];
		for(int i=nRow*2;i>0;i--) {
			for(int j=0;j<Lang[s+i].length;j++) {
				if(Lang[s+i][j]==str)
					return Lang[s+i-(i<nRow?0:nRow)][j];//返回对应英语命令串;
			}
		}return "xxx";									//未找到匹配项,返回错误串;
	}
	//v0.34;20221005;将原init()中创建键盘按钮的程序段独立为方法,便于实现中英双语界面;
	//v0.40;20221230;AWT2Swing直接升级版;并增加中文悬停提示;
	//v0.41;20230102;为新增的双语串组LANG[][]专门改写的版本;
	private void CreateButtons(JPanel owner,String[][] Lang,int s) {
		int nRow=Integer.parseInt(Lang[s+0][1]);		//键组行数@[s+0][1];
		JButton [][]keys = new JButton[nRow][];			//创建按钮组;
		for (int i = 0; i < nRow; i++){
			keys[i] = new JButton[Lang[s+1+i].length];
			for (int j = 0; j < Lang[s+1+i].length; j++){
				keys[i][j] = new JButton(Lang[s+1+i+(iLang==0?0:nRow)][j]);	//创建单个按钮,按钮名@kLang[][];
				keys[i][j].setToolTipText(Lang[s+1+i+(iLang==0?nRow:0)][j]);	//光标悬停中文提示;
				keys[i][j].addActionListener(new MyKeysListen());//监听注册;动作响应@MyKeysListen();
				owner.add(keys[i][j]);           		//放置按钮@物主owner;
			}
		} 
	}
	//v0.34;20221005;将原init()中创建菜单的程序段独立为方法,便于实现中英双语界面;
	//v0.40;20221230;AWT2Swing直接升级版,并增加中文悬停提示;
	//v0.41;20230102;为新增的双语串组LANG[][]专门改写的版本;
	private void CreateMenu(JMenuBar owner,String[][] Lang,int s) {
		int nRow=Integer.parseInt(Lang[s+0][1]);		//菜单length;
		JMenu []menu = new JMenu[nRow];
		JMenuItem [][]mItem = new JMenuItem[nRow][];
		//自定义菜单监听执行动作类MyMenuListen(),事件统一响应;【核心类】
		MyMenuListen mbl = new MyMenuListen();			//创建菜单监听类实例;		
		//菜单分类创建/注册/放置;命名@MENU[][];分隔线fileMenu.addSeparator();
		for (int i = 0; i < nRow; i++){
			menu[i] = new JMenu(Lang[s+1+i+(iLang==0?0:nRow)][0]);		//创建菜单;
			menu[i].setToolTipText(Lang[s+1+i+(iLang==0?nRow:0)][0]);//光标悬停中文提示;
			menu[i].addActionListener(mbl);				//监听注册;动作响应@MyMenuListen();
			owner.add(menu[i]);           				//放置菜单@物主owner;
			mItem[i] = new JMenuItem[Lang[s+1+i].length-1];
			for (int j = 0; j < Lang[s+1+i].length-1; j++){
				mItem[i][j] = new JMenuItem(Lang[s+1+i+(iLang==0?0:nRow)][j+1]);	//创建菜单项;
				mItem[i][j].setToolTipText(Lang[s+1+i+(iLang==0?nRow:0)][j+1]);	//光标悬停中文提示;
				mItem[i][j].addActionListener(mbl);		//监听注册;动作响应@MyMenuListen();
				menu[i].add(mItem[i][j]);         		//放置菜单项;
			}
		}
	}
	//------------------------------------	
	//v0.34;初始化"关于"对话框about;v0.33新增;
	//v0.41;20230107;为新增的双语串组LANG[][]专门改写的版本;
	private void aboutInit(JFrame owner,String[][] Lang) 
  	{
		int s = classIndex("about",Lang);
		int nRow = Integer.parseInt(Lang[s+0][1]);
		int wAbout = Integer.parseInt(Lang[s+0][2]);
  	  	int hAbout = Integer.parseInt(Lang[s+0][3]);
  	  	JDialog about = new JDialog(owner,Lang[s+1+(iLang==0?0:nRow)][0],true);
  	  	JLabel 	info  = new JLabel(Lang[s+1+(iLang==0?0:nRow)][1],JLabel.CENTER);
  	  	info.setToolTipText(Lang[s+1+(iLang==0?nRow:0)][1]);			//光标悬停中文提示;
  		about.setSize(wAbout,hAbout);
  		about.add(info,"Center");		//,BorderLayout.CENTER;	
  		about.setLocationRelativeTo(owner);				//位置跟随;关联frame;
  		about.setResizable(false);						//默认true;
  		about.addWindowListener(new MyWinListen());		//注册窗口监听器;MyWinListen;
  		about.setVisible(true);
  	}     
    //v0.41;20230102w1;创新的主框架初始化;为新增的双语串组LANG[][]专门改写的版本;
	private void frameInit(String[][] Lang)		
    {
    	int nRow;										//本类行数@Lang[s+0][1];
		for (int i=0;i < Lang.length; i++) {
    		switch(Lang[i][0]) {
    		case "language":
    			//iLang = (Lang[i][2]=="0"?0:1);		//默认定制;菜单切换时不需要;
    			break;	
    		case "frame":
    			nRow = Integer.parseInt(Lang[i+0][1]);
    			wFrame = Integer.parseInt(Lang[i+0][2]);
    			hFrame = Integer.parseInt(Lang[i+0][3]);
    			Image im = (new ImageIcon(Lang[i+0][4])).getImage();
    			frame = new JFrame(Lang[i+1+(iLang==0?0:nRow)][0]);	//窗口标题title;
    	    	frame.setIconImage(im);					//主窗口图标;
    			frame.setSize(wFrame+(iLang==0?0:43),hFrame);			//主窗口大小;
    	    	frame.setBackground(Color.lightGray);	//自定义深蓝Color(0,64,96);推荐Color.lightGray;
    	    	frame.setLocationRelativeTo(null);		//将窗口居中;若无该方法,窗口将位于屏幕左上角;    	
    	    	//frame.setResizable(false); 			//禁止调整窗口大小。默认允许调整窗口尺寸;
    	    	break;
    		case "textshow":
    			nRow = Integer.parseInt(Lang[i+0][1]);
    			int rRow = Integer.parseInt(Lang[i+0][2]);
    			int rCol = Integer.parseInt(Lang[i+0][3]);
    			tRecord = new JTextArea(Lang[i+1+(iLang==0?0:nRow)][0],rRow,rCol);//创建文本区,操作记录显示区;
    			tRecord.setToolTipText(Lang[i+1+(iLang==0?nRow:0)][0]);	//光标悬停中文提示;
    	    	frame.add(tRecord,"West");
    	    	tResult = new JTextField(Lang[i+1+(iLang==0?0:nRow)][1],rCol);//创建单个文本行,文本名@tLang[1][];
				tResult.setToolTipText(Lang[i+1+(iLang==0?nRow:0)][1]);	//光标悬停中文提示;
    	    	frame.add(tResult,"North");
    	    	break;
    		case "pkeys":
    			JPanel pkeys = new JPanel();			//按键板;默认7行8列;
    			int kRow = Integer.parseInt(Lang[i][1]);//键组行数;
    			int kCol = Integer.parseInt(Lang[i][2]);//键组列数;
    			pkeys.setLayout(new GridLayout(kRow,kCol,1,1));	//设置布局;网格间距行列(1,1);         
    	    	CreateButtons(pkeys,Lang,i);			//创建按键板;简单DIY;
    	    	frame.add(pkeys,"East");				//顺序在前,上层优先;
    		 	break;
    		case "menu":
    	        JMenuBar mbar = new JMenuBar();
    	    	CreateMenu(mbar,Lang,i);				//创建菜单;简单DIY;   
    	    	frame.setJMenuBar(mbar);
    		}
    	}
  		frame.addWindowListener(new MyWinListen());
	    frame.setVisible(true);	
    }
    
    //构造方法:
    private Calculate() {
    	frameInit(LANG);
    }
    
    //------------------------------------
  	//v0.34;20221001;自定义菜单监听事件响应类;(监听事件响应;计算器控制主体)【核心类】	
  	class MyMenuListen implements ActionListener		//监听接口实现类;
  	{			
  		//菜单项menuItem动作响应;--接口实现方法;
  		private void ActMenu(String act) {				//菜单动作;菜单项mi;【核心方法】					
  			switch(act){		
  			case "Open"	: break;
  			case "Save"	: break;
  			case "Reset": frame.setSize(wFrame,hFrame);break;
  			case "tTip" : tResult.setText(iLang==0?"计算结果":"tResult");
  						tRecord.setText(iLang==0?"操作记录区:\n":"tRecord\n");break;
  			case "tShow": tRecord.append("\n"+"mem="+mem+"\n");
  						tRecord.append("num1+Oper+num2=tResult\n");
  						tRecord.append(num1+Oper+num2+"\n="+tResult.getText()+"\n");
  						break;
  			case "Exit"	: System.exit(0);break;
  			case "Typical": frame.setSize(wFrame-(iLang==0?132:104),hFrame);break;
  			case "Personal": frame.setSize(wFrame-(iLang==0?66:30),hFrame);break;
  			case "Multifunc": frame.setSize(wFrame+(iLang==0?132:192),hFrame+49);break;
  			case "Default": frame.setSize(wFrame+(iLang==0?0:43),hFrame);break;
  			case "About": aboutInit(frame,LANG);break;			
  			case "English": iLang=0;frameInit(LANG);break;	
  			case "Chinese": iLang=1;frameInit(LANG);break;
  			}	
  		}
  		//继承关系:Component.AbstractButton.MenuItem.Menu;
  		public void actionPerformed(ActionEvent e){		//执行动作(动作事件e);按钮响应;			
  			String mcmd = e.getActionCommand();			//获取动作命令;菜单命令串名@MENU[];			  			
  			//预置动作;
  			tRecord.append(mcmd);						//追加菜单操作记录;
  			if(iLang!=0)mcmd=cmdIndex(mcmd,"menu",LANG);//将非英语字串转换为英文字串;
  			//标准动作;
  			ActMenu(mcmd);								//执行菜单命令串;
  		}	
  	}
  	
  	//------------------------------------ 
	//v0.34;20221005;自定义按键监听事件响应类;(监听事件响应;计算器运行主体;)【核心类】	
	class MyKeysListen implements ActionListener {		//监听接口实现类;	

		//按键分类;--按键动作分类预处理:其它按钮无需列出;
		private final String []opNumf = {
				"0","1","2","3","4","5","6","7","8","9",
				"a","b","c","d","e","f",".",}; 			//浮点数&hex按钮;	
		private final String []opNum1 = {
				"x^2","x^3","sqrt","cbrt","1/x","n!","-/+","hex",
				"rand","sin","cos","tan","log1",}; 		//一元操作符;
		private final String []opNum2 = {"+","-","*","/","%","x^y",};	//二元操作符;
		//按键动作分类方法;
		private boolean opClass(String []array, String op){			//操作动作的分类方法;串组元素确认;
			for(String element:array)if(element==op) return true;	//--JDK5.0以后新增foreach语句;
			return false;
		}
		//转换整数int到16进制串;
		private String opHexStr(String []array, double num){	//标准名Int2HexStr();
			String hexStr="";int d=(int)num;					//十进制d;16进制串hexStr;
			do{hexStr=opNumf[d%16]+hexStr;d/=16;}while(d!=0);
			return hexStr;
		}
		//预处理动作@1~4;
		private void ActInput(String act) {				//输入动作;分类响应的预处理方法;			
							
			if(opClass(opNumf,act)==true) {				//1.数字拼接@tfResult;					
				if(isNum==true) {
					String ts=tResult.getText();		//继续拼接;临时串ts;
					tResult.setText(ts+act);			//追加动作串act;
				}else tResult.setText(act);				//重新拼接;
				isNum=true;return;						//首位数字拼接@ks;	
			}
			if(opClass(opNum2,act)==true) {				//2.双元操作符@Oper;
				num1=Double.parseDouble(tResult.getText());	
				isNum=false;Oper=act;return;			//双元操作符@"="时延迟生效;
			}			
			if(act=="=") {								//3.等号计算;双元计算num2;				
				num2=Double.parseDouble(tResult.getText());
				isNum=false;return;							
			}
			if(opClass(opNum1,act)==true) {				//4.一元操作符;
				num1=Double.parseDouble(tResult.getText());	//转化为double;
				tRecord.append("=");	
				isNum=false;return;
			}		
		}
		//计算动作@5~7;
		private void ActCalc(String act) {				//计算动作;核心计算方法;
			
			switch(act){
			//预处理动作@1~4;
			//5.主要计算动作;
			case "hex"	:
				tResult.setText("0x"+opHexStr(opNumf,num1));break;//Int2HexStr;
			case "n!":
				int n=1;int t=(int)num1;do{n*=t--;}while(t!=1);
				tResult.setText(n+"");break;				//整数n的阶乘;
			case "cbrt"	:tResult.setText(Math.cbrt(num1)+"");break;//CubeRoot;
			case "sqrt"	:tResult.setText(Math.sqrt(num1)+"");break;//SquareRoot;
			case "x^3"	:tResult.setText(Math.pow(num1,3)+"");break;//Math.pow(a,b)取a的b次幂;				
			case "x^2"	:tResult.setText(Math.pow(num1,2)+"");break;//
			case "1/x"	:tResult.setText(1/num1+"");break;	//除0显示Infinity错误;
			case "-/+"	:tResult.setText(0-num1+"");break;	//正负转换;
			case "="	:
				switch(Oper) {								//等号操作;二元计算;
				case "+"	:tResult.setText(num1+num2+"");break;
				case "-"	:tResult.setText(num1-num2+"");break;
				case "*"	:tResult.setText(num1*num2+"");break;
				case "/"	:tResult.setText(num1/num2+"");break;
				case "%"	:tResult.setText(num1%num2+"");break;
				case "x^y"	:tResult.setText(Math.pow(num1,num2)+"");break;//Math.pow(x,y);
				}break;
			//6.辅助计算动作;
			case "M":
				if(mem==0) {
					tRecord.append("MS");				//记忆保存MS;
					mem=Double.parseDouble(tResult.getText());
				}else {
					tRecord.append("MR");				//记忆读取MR;
					tResult.setText(mem+"");isNum=true;
				}tRecord.append("\nmem="+mem+"\n");break;
			case "MC":tRecord.append("MC");mem=0;		//记忆清空MC;	
				tRecord.append("\nmem="+mem+"\n");break;							
			case "PI":tResult.setText(Math.PI+"");isNum=true;break;	//圆周率;PI=3.141592653589793-2384626;
			case "E" :tResult.setText(Math.E+"");isNum=true;break;	//Euler;E=2.718281828459045-2354;
			//7.特殊动作;
			case "BS":									//退格BackSpace;
				tResult.setText(tResult.getText().substring(0,tResult.getText().length()-1));
				break;								
			case "C":									//Copy&Clear;
				tRecord.append("\n="+tResult.getText()+"\n");//拷贝结果至记录区并换行;			
				tResult.setText("0");break;	
			case "CR" :
				num1=num2=mem=0;
				tRecord.setText("num1=num2=mem=0\n");break;	//清空记录区;			
			}		
		}
		
		//按钮动作响应;--接口方法;
		public void actionPerformed(ActionEvent e){		//执行动作(动作事件e);按钮响应;			
			String key = e.getActionCommand();			//获取按键动作命令;即按键串名key@KEYS[];			
			//预置动作;
			if(""==tResult.getText())tResult.setText("0");//避免空串赋值;	
			tRecord.append(key);						//操作动作记录;将键名追加到记录区文本;	
			if(iLang!=0)key=cmdIndex(key,"pkeys",LANG);	//将非英语字串转换为英文命令字串;
			//标准动作;
			ActInput(key);								//输入动作;				
			ActCalc(key);								//计算动作;
		}	
	}
	//------------------------------------		
	//v0.33;20221001;退窗口事件响应类;
	//exit.addActionListener(e->System.exit(0));	
	class MyWinListen extends WindowAdapter{		
		public void windowClosing(WindowEvent e){
			e.getWindow().setVisible(false);			//关闭窗口;
			e.getWindow().dispose();					//释放资源;
			if(e.getSource()==frame)
				System.exit(0);							//完全退出;
		}
	}
	//------------------------------------
	//v0.33;20221001;主方法;
	//v0.41;20230103;创新版,使用多语言数据包初始化;
    public static void main(String[] args)
    {  	
        new Calculate();								//用构造方法创建实例;主框架初始化;
    }
}

//----------------------------------------------------------------------------*/

三、运行效果:(截图)

中英文界面对比:(对话窗口自动跟随主窗口)
在这里插入图片描述

中文窗口的“语言”菜单:(多功能界面)
在这里插入图片描述
中文窗口的“帮助”菜单:(双语提示效果)
在这里插入图片描述
英文窗口中的“选项–>典型”计算器界面:(简易型界面)
在这里插入图片描述
网页在中英文浏览器环境下的自适应显示效果:
在这里插入图片描述

Win10的显示语言可以下载/安装/卸载:
在这里插入图片描述
IE浏览器切换使用语言@工具→Internet选项:
在这里插入图片描述

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

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

相关文章

C++ 20 原子引用 (一)

C 20 原子引用 &#xff08;一&#xff09; std::atomic_ref{} std::atomic_ref类型对其引用的对象进行原子操作。 使用std::atomic_ref 进行多线程读写时不会造成数据争用。被引用对象的生命周期必须超过std::atomic_ref 。操作std::atomic_ref 的子对象是未定义行为。 错…

Docker版RabbitMQ安装延迟队列插件及延迟队列项目应用实战

前言 在项目中经常有延迟业务处理的背景&#xff0c;此时可以借助于Rabbitmq的延迟队列进行实现&#xff0c;但Rabbitmq本身并不支持延迟队列&#xff0c;但可以通过安装插件的方式实现延迟队列 环境准备 首先确认目前项目使用的Rabbitmq的版本&#xff0c;这里博主的版本是3.…

STM32系列(HAL库)——使用ESP8266-01S物联网模块连接Onenet云平台上报DHT11温湿度

前言 本篇主要讲解如何使用ESP8266-01S物联网模块连接Onenet云平台&#xff0c;并上报DHT11模块的温湿度数据。本文单片机主控采用STM32F405RGT6&#xff0c;使用其他主控的话基本要求有2个串口&#xff0c;一个串口用于调试使用&#xff0c;另一个用于ESP模块通讯。 一、前…

SOLIDWORKS 2023工程图和出详图新功能 创建更智能化 更高精度的工程详图

工程图是传达您设计意图的重要文档&#xff0c;您设计的产品越复杂&#xff0c;越需要详细注释说明。SOLIDWORKS 2023增强的工程图和出详图功能将帮助您创建更智能化、更高精度的工程详图&#xff0c;并且扩展新功能使您的设计工作延伸到更多的业务领域。您现在可以从更高层级的…

C 程序设计教程(15)—— 选择结构程序设计练习题

C 程序设计教程&#xff08;15&#xff09;—— 选择结构程序设计练习题 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用户阅读。 目录C 程序设计教程&#xff08;1…

20230110配置ubuntu18.04为开机自动登录

20230110配置ubuntu18.04为开机自动登录 百度搜索&#xff1a;ubuntu 18.04 开机自动登录 https://blog.csdn.net/yang1994/article/details/124446319 通过配置文件启用/禁用Ubuntu 18.04自动登录 超级用户可以通过编辑custom.conf配置文件的方式&#xff0c;来为自己或任何其…

计算机如何存储浮点数和定点数?

1 浮点数的不精确性 能不能用二进制表示所有实数&#xff0c;然后在二进制下计算它的加减乘除呢&#xff1f; 打开Chrome Console&#xff0c;输入0.3 0.6&#xff1a; 简单加法在js算出结果居然不是准确的0.9&#xff0c;而是0.8999999999999999&#xff0c;why&#xff1…

火山语音丨AI创作惊艳四方 诸多挑战仍在路上

2022年8月&#xff0c;一幅名为《太空歌剧院》的数字画作获得冠军同时引发了巨大争议&#xff0c;AIGC&#xff08;AI产生内容&#xff1a;AI-Generated Content&#xff09;出圈的事件便频频出现在大众视野。同年11月30日OpenAI发布的聊天机器人模型ChatGPT免费开放&#xff0…

从0到1完成一个Vue后台管理项目(二十、地图涟漪、线图)

往期 从0到1完成一个Vue后台管理项目&#xff08;一、创建项目&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;二、使用element-ui&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;三、使用SCSS/LESS&#xff0c;安装图标库&#xff09; 从0到1完成一个Vu…

缓存穿透、布隆过滤器、布谷鸟过滤器

1.概述 缓存穿透&#xff1a; 当查询的数据在缓存&#xff08;redis&#xff09;中没有时&#xff0c;一般业务上就会去查询数据存储&#xff08;数据库&#xff09;&#xff0c;这种情况称为缓存穿透。穿透的数量太大会造成数据存储撑不住&#xff08;数据库&#xff09;而宕…

基于控制器软件需求事项进行单元测试和单元测试规范

基于需求事项的单元测试是什么&#xff1f; ​ 大多数汽车行业都遵循 ISO 26262 中定义的标准&#xff0c;这是 ISO 制定的汽车功能安全国际标准。 根据 ISO 26262 标准软件单元测试 (ISO 26262-6-9)&#xff0c;单元验证是验证要验证的单元&#xff08;功能或功能&#xff09…

智能优化算法应用:基于蜣螂优化算法的工程优化案例

智能优化算法应用&#xff1a;基于蜣螂算法的工程优化案例 文章目录智能优化算法应用&#xff1a;基于蜣螂算法的工程优化案例1.蜣螂算法2.压力容器设计问题3.三杆桁架设计问题4.拉压弹簧设计问题5.Matlab代码6.Python代码摘要&#xff1a;本文介绍利用蜣螂搜索算法&#xff0c…

MyBatis框架知识点总结

一、引言1.1 什么是框架&#xff1f;框架&#xff1a;框架使用你的&#xff0c;而不是你在使用框架的。框架让我们提供什么信息&#xff0c;配置信息&#xff0c;数据库连接用户名密码等&#xff0c;你必须提供&#xff0c;还得按照框架要要求的方式提供&#xff0c;否则你就别…

《图机器学习》-Node Embeddings

Node Embeddings一、Graph Representation Learning二、Node Embeddings&#xff1a;Encoder and Decoder三、Random Walk Approaches for Node Embeddings一、Graph Representation Learning 在传统的图机器学习中&#xff0c;依赖于手工特征工程(即由特征工程师去设计节点、…

每日一题:Leetcode54. 螺旋矩阵

文章目录 系列&#xff1a;数组专练 语言&#xff1a;java & go 题目来源&#xff1a;Leetcode54. 螺旋矩阵 难度&#xff1a;中等 考点&#xff1a;边界问题处理 思路和参考答案文章目录题目描述思路java参考代码go参考代码&#xff1a;题目描述 给你一个 m 行 n 列的矩…

力扣sql基础篇(三)

力扣sql基础篇(三) 1 查询结果的质量和占比 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # 把该列置为null的话,它就不会统计了 SELECT query_name,ROUND(sum(rating/position)/count(*),2) quality, ROUND(count(IF(rating<3,rating,null))/c…

【数据结构】—— Java实现双向链表

Java实现双向链表一、链表的概念及结构二、头指针与头结点的异同三、代码实现一、链表的概念及结构 我们在单链表中&#xff0c;有了next指针。这就使得我们查找下一个结点的时间复杂度为O(1)。可是我们要查找的是上一个结点的话&#xff0c;那最坏的时间复杂度就是O(n)了&…

用图记忆C语言中的运算符优先级

运算符优先级以及结合方向的统计表&#xff0c;网上到处可见。本文画了一张图&#xff0c;以便记忆&#xff01; 1. 总体来说优先级 初级运算 > 单目运算 > 双目运算 > 三目运算 > 赋值运算 > 逗号运算 2. 双目细分 算术运算 > 位移运算 > 关系运算 &g…

今年十八,基础过关

目录 前言 第一关&#xff1a;KEY在哪里 再加密一次你就得到key啦~ 猜猜这是经过了多少次加密&#xff1f; 据说MD5加密很安全&#xff0c;真的是么&#xff1f; 种族歧视 HAHA浏览器 key究竟在哪里呢&#xff1f; key又找不到了 冒充登陆用户​编辑 比较数字大小 就不让你…

Linux应用编程---14.UDP服务器、客户端编程

Linux应用编程—14.UDP服务器、客户端编程 ​ 之前有介绍过UDP是一种无连接、尽最大努力交付、面向报文的协议。应用层交给UDP多长的报文&#xff0c;UDP就照样发送。Linux下UDP属于数据报socket。数据报socket流程图如图1所示&#xff1a; 图1 数据报socket流程图 ​ 新引入的…