JavaFX简单音乐播放器
最近用javaFX写了一个音乐播放器,用swing感觉自定义界面太麻烦了所以用了 javaFX 因为时间关系我就只学了自定义界面和音乐的触发事件,小白一枚 写的代码可能会不规范。请大家谅解
然后用到了数据库的方式存放歌曲的地址,因为我这个萌新还没有学用网络爬取歌曲,所以歌曲存放在本地
哇,我一直以为//# java这个才是 标题搞了好久一直提示我请勿使用默认标题搞了好久才知道
这个才是标题(捂脸)
下面是效果图
下面是代码
代码变量初始化
public class Main extends Application{public static void main(String[] args) {launch(args);
}Music_Dao music_Dao =new Music_Dao();//这个是dao层下的包等会调用数据库时用到的
Media media;
MediaPlayer mediaPlayer;
HashMap<Integer, String> hashMap_song;
help help_method;
ObservableList<String> observableList;//一个存放歌曲地址的一个集合
int flage=0;//歌曲列表的索引
//用来拖动
double x=0;//定义一个x用来存放鼠标在窗口的当前x轴位置
double y=0;//定义一个y用来存放鼠标在窗口的当前y轴位置
boolean max_is=true;//用来判断当前窗口是否是最大化状态 true:是 false:否
boolean is_play=true;//判断一个歌曲是否真正播放
boolean is_mouse=false;//用来判断鼠标是否在进度条上
Label setbackgroud;//用来存放播放时用的模糊图片
Slider slider;//以下是歌曲的信息 名字、演唱者、歌曲类型、歌曲图片
Label song_name;
Label song_songer;
Label song_type;
Label song_image;
下面是重写Application类中的 start()方法
@Overridepublic void start(Stage primaryStage) throws Exception {//下面是给关闭 最大化 最小化 按钮 自定义样式HBox hBox_title=new HBox();//给关闭按钮设置图片ImageView imageView =new ImageView("image/关闭.png");imageView.setFitWidth(23);imageView.setFitHeight(13);Button close_button=new Button("",imageView);close_button.setStyle("-fx-background-color:#FF8C0000;");ImageView imageView2 =new ImageView("image/最大化.png");imageView2.setFitWidth(23);imageView2.setFitHeight(13);Button Max_button=new Button("",imageView2);Max_button.setStyle("-fx-background-color:#FF8C0000;");ImageView imageView3 =new ImageView("image/最小化.png");imageView3.setFitWidth(23);imageView3.setFitHeight(13);Button Min_button=new Button("",imageView3);Min_button.setStyle("-fx-background-color:#FF8C0000;");hBox_title.getChildren().addAll(Min_button,Max_button,close_button);//以下是登录注册按钮HBox hBox_LoginandRegister=new HBox(2);Button Login_Button=new Button("登录");Login_Button.setPrefWidth(60);//设置宽Login_Button.setPrefHeight(20);//设置高Login_Button.setTextFill(Color.web("#d479f2"));//设置文本颜色Login_Button.setFont(Font.font(18));Login_Button.setStyle("-fx-background-color:#26075100;" +// 设置按钮背景颜色"-fx-border-insets:5;" //边框距离按钮的距离);Label division =new Label("|");division.setTextFill(Color.web("#e08afc"));Button Register_Button =new Button("注册");Register_Button.setPrefWidth(60);Register_Button.setPrefHeight(20);Register_Button.setFont(Font.font(18));Register_Button.setTextFill(Color.web("#d479f2"));Register_Button.setStyle("-fx-background-color:#26075100;" +// 设置按钮背景颜色"-fx-border-insets:5;" //边框距离按钮的距离);hBox_LoginandRegister.getChildren().addAll(Login_Button,division,Register_Button);hBox_LoginandRegister.setAlignment(Pos.CENTER);//以下是播放和暂停按钮以及切歌按钮的自定义样式HBox hBox_play =new HBox();ImageView imageView4 =new ImageView("image/播放.png");imageView4.setFitWidth(76);imageView4.setFitHeight(55);Button play_button=new Button("",imageView4);play_button.setStyle("-fx-background-color:#FF8C0000;");ImageView imageView5 =new ImageView("image/下一首.png");imageView5.setFitWidth(76);imageView5.setFitHeight(55);Button next_button=new Button("",imageView5);next_button.setStyle("-fx-background-color:#FF8C0000;");ImageView imageView6 =new ImageView("image/上一首.png");imageView6.setFitWidth(76);imageView6.setFitHeight(55);Button last_button =new Button("",imageView6);last_button.setStyle("-fx-background-color:#FF8C0000;");hBox_play.getChildren().addAll(last_button,play_button,next_button);//以下是界面中左边的一个列表VBox vBox_listView=new VBox();observableList=FXCollections.observableArrayList();getsongname();查询数据库的歌曲列表 并放进list 里面ListView<String> listView=new ListView<>(observableList);listView.setPrefWidth(200);listView.setPrefHeight(410);//这个也不知道为什么没有用
// listView.setStyle("-fx-background-insets:0;"
// + "-fx-padding:0;"
// + "-fx-background-color:#eb9de9;"
// + "-fx-background-fills:#eb9de9;"
// + "-fx-border-radius:10;"
// );vBox_listView.getChildren().add(listView);hashMap_song =new HashMap<>();get_song_map();URL frist_music=this.getClass().getClassLoader().getResource(hashMap_song.get(0));media =new Media(frist_music.toExternalForm());mediaPlayer =new MediaPlayer(media);//进度条初始化slider =new Slider();slider.setPrefWidth(825);//模糊背景标签初始化 因为我在setbackgroud=new Label();//歌曲信息标签初始化VBox vbox_TitleandImage=new VBox(10);song_image =new Label();VBox vBox_songmessage=new VBox(10);song_name=new Label();song_songer=new Label();song_type=new Label();vbox_TitleandImage.getChildren().addAll(song_name,song_image);vbox_TitleandImage.setAlignment(Pos.CENTER_LEFT);vBox_songmessage.getChildren().addAll(song_songer,song_type);AnchorPane aPane =new AnchorPane();//把小容器都装到大容器里面aPane.getChildren().addAll(hBox_title,hBox_play,vBox_listView,slider,setbackgroud,vbox_TitleandImage,vBox_songmessage,hBox_LoginandRegister);aPane.setBottomAnchor(vBox_listView, 55.0);aPane.setRightAnchor(hBox_title, 10.0);aPane.setBottomAnchor(hBox_play, 30.0);aPane.setRightAnchor(hBox_play, 310.0);aPane.setBottomAnchor(slider, 90.0);aPane.setRightAnchor(slider,0.0);aPane.setLeftAnchor(setbackgroud, 201.0);aPane.setBottomAnchor(setbackgroud, 107.0);aPane.setBottomAnchor(vbox_TitleandImage, 251.0);aPane.setLeftAnchor(vbox_TitleandImage,497.0);aPane.setLeftAnchor(vBox_songmessage, 499.0);aPane.setBottomAnchor(vBox_songmessage, 190.0);aPane.setTopAnchor(hBox_LoginandRegister, 30.0);aPane.setLeftAnchor(hBox_LoginandRegister, 20.0);//设置根节点圆角显示Background bg =new Background(new BackgroundFill(Paint.valueOf("#00000000"), new CornerRadii(20) , new Insets(0)));aPane.setBackground(bg);aPane.setStyle("-fx-background-radius: 20px;"+ "-fx-background-image:url(image/背景.png);");Scene scene =new Scene(aPane);//把场景图的颜色设置为透明不然会露出来一点角scene.setFill(Paint.valueOf("#00000000"));primaryStage.setScene(scene);primaryStage.setWidth(1025);primaryStage.setHeight(603);primaryStage.setTitle("Mark1");primaryStage.setResizable(false);
// //设置窗口的样式为null,所以你要自己定义一个关闭、最小化、最大化的按钮primaryStage.initStyle(StageStyle.TRANSPARENT);primaryStage.getIcons().add(new Image("/image/logo.jpg"));primaryStage.setTitle("捡垃圾播放器");primaryStage.show();//以下都是监听方法scene.setOnMousePressed(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {x=event.getScreenX()-primaryStage.getX();y=event.getScreenY()-primaryStage.getY();}});scene.setOnMouseDragged(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {primaryStage.setX(event.getScreenX()-x);primaryStage.setY(event.getScreenY()-y);}});//下面是标题栏按钮的监听方法close_button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent event) {primaryStage.close();}});//设置当鼠标移动在按钮上面的监听close_button.setOnMouseMoved(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {if(true) {// ImageView imageView =new ImageView("image/关闭副.png");imageView.setFitWidth(23);imageView.setFitHeight(13);//改变按钮里的图片我也不知道它干嘛弄一个Graphic这个来设置这些,我裂开了close_button.setGraphic(new ImageView("image/关闭副.png"));
// close_button=new Button("",imageView);close_button.setStyle("-fx-background-color:#FF8C0000;");
// hBox_title.getChildren().add(close_button);}}});//设置当鼠标离开按钮上面的监听close_button.setOnMouseExited(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {close_button.setGraphic(new ImageView("image/关闭.png"));}});Max_button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent event) {System.out.println(max_is);if(max_is) {primaryStage.setMaximized(true);max_is=false;}else {max_is=true;primaryStage.setMaximized(false);}}});Max_button.setOnMouseMoved(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {if(true) {Max_button.setGraphic(new ImageView("image/最大化副.png"));Max_button.setStyle("-fx-background-color:#FF8C0000;");}}});Max_button.setOnMouseExited(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {Max_button.setGraphic(new ImageView("image/最大化.png"));}});Min_button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent event) {primaryStage.setIconified(true);}});Min_button.setOnMouseMoved(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {if(true) {Min_button.setGraphic(new ImageView("image/最小化副.png"));Min_button.setStyle("-fx-background-color:#FF8C0000;");}}});Min_button.setOnMouseExited(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {Min_button.setGraphic(new ImageView("image/最小化.png"));}});//以下是登录和注册按钮事件监听Login_Button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent event) {Stage LoginStage=new Stage();Login login =new Login();try {login.start(LoginStage);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}});Login_Button.setOnMouseMoved(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {Login_Button.setTextFill(Color.web("#eb9de9"));}});Login_Button.setOnMouseExited(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {Login_Button.setTextFill(Color.web("#d479f2"));}});Register_Button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent event) {}});Register_Button.setOnMouseMoved(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {Register_Button.setTextFill(Color.web("#eb9de9"));}});Register_Button.setOnMouseExited(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {Register_Button.setTextFill(Color.web("#d479f2"));}});//以下是播放和暂停按钮以及切歌按钮的事件监听play_button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent event) {if(is_play==true) {mediaPlayer.pause();is_play=false;setbackgroud.setGraphic(null);}else {is_play=true;play_button.setGraphic(new ImageView("image/暂停副.png"));mediaPlayer.play();SliderListener();SetbackgroudAndsongImage();}}});play_button.setOnMouseMoved(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {if(is_play==true) {play_button.setGraphic(new ImageView("image/播放副.png"));}else {play_button.setGraphic(new ImageView("image/暂停副.png"));}
// play_button.setGraphic(new ImageView("image/播放副.png"));
// play_button.setStyle("-fx-background-color:#FF8C0000;");}});play_button.setOnMouseExited(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {if(is_play==true) {play_button.setGraphic(new ImageView("image/播放.png"));}else {play_button.setGraphic(new ImageView("image/暂停.png"));}}});play_button.setOnMouseClicked(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {// play_button.setGraphic(new ImageView("image/暂停副.png"));}});last_button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent event) {mediaPlayer.dispose();flage=flage-1;if(flage==-1) {flage=hashMap_song.size()-1;}URL flage_music=this.getClass().getClassLoader().getResource(hashMap_song.get(flage));media =new Media(flage_music.toExternalForm());mediaPlayer =new MediaPlayer(media);mediaPlayer.play();SliderListener();}});last_button.setOnMouseMoved(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {if(true) {last_button.setGraphic(new ImageView("image/上一首副.png"));last_button.setStyle("-fx-background-color:#FF8C0000;");}}});last_button.setOnMouseExited(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {last_button.setGraphic(new ImageView("image/上一首.png"));}});next_button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent event) {mediaPlayer.dispose();flage=flage+1;System.out.println("nextflag "+flage);if(flage==hashMap_song.size()) {flage=0;}URL flage_music=this.getClass().getClassLoader().getResource(hashMap_song.get(flage));media =new Media(flage_music.toExternalForm());mediaPlayer =new MediaPlayer(media);mediaPlayer.play();SliderListener();}});next_button.setOnMouseMoved(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {if(true) {next_button.setGraphic(new ImageView("image/下一首副.png"));next_button.setStyle("-fx-background-color:#FF8C0000;");}}});next_button.setOnMouseExited(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {next_button.setGraphic(new ImageView("image/下一首.png"));}});//下面是自定义列表的初始化listView.setOnMouseClicked(new EventHandler<MouseEvent>() {@Overridepublic void handle(MouseEvent event) {// TODO Auto-generated method stubmediaPlayer.dispose();flage=listView.getSelectionModel().getSelectedIndex();System.out.println(hashMap_song.get(flage));URL flage_music=this.getClass().getClassLoader().getResource(hashMap_song.get(flage));media =new Media(flage_music.toExternalForm());mediaPlayer =new MediaPlayer(media);mediaPlayer.play();SliderListener();SetbackgroudAndsongImage();System.out.println(flage);}});listView.setCellFactory(TextFieldListCell.forListView(new StringConverter<String>() {public String toString(String object) {// TODO Auto-generated method stubString string =object;return string;}@Overridepublic String fromString(String string) {// TODO Auto-generated method stubreturn null;}
}));listView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {@Overridepublic ListCell<String> call(ListView<String> param) {// TODO Auto-generated method stubListCell<String> listCell =new ListCell<String>() {@Overrideprotected void updateItem(String item, boolean empty) {// TODO Auto-generated method stubsuper.updateItem(item, empty);if(empty== false) {HBox hBox =new HBox();Label label =new Label(item.toString());hBox.getChildren().add(label);hBox.setStyle("-fx-background-color:#eb9de9");this.setGraphic(hBox); }}};return listCell;}});//以下是进度条监听方法slider.setOnMouseReleased(new EventHandler<MouseEvent>() {public void handle(MouseEvent event) {// TODO Auto-generated method stubis_mouse=false;mediaPlayer.seek(Duration.seconds(slider.getValue()));SliderListener();}});slider.setOnMousePressed(new EventHandler<MouseEvent>() {public void handle(MouseEvent event) {// TODO Auto-generated method stuis_mouse=true;}});}
下面是一些重复的代码我就把它装在方法里面了
public void getsongname() throws SQLException {//使用数据库添加数据List<Music_Bean> list_music=music_Dao.select();for(Music_Bean music:list_music) {observableList.add(music.getName());}
}
//查询数据库的歌曲列表 并放进list 里面
public void get_song_map() throws SQLException {List<Music_Bean> list_music=music_Dao.select();for(Music_Bean music:list_music) {System.out.println(music.getId()-1+" "+music.getUrl());hashMap_song.put(music.getId()-1, music.getUrl());}System.out.println(hashMap_song);
}
//用来加载歌曲的信息,歌曲的image\name\type\time
public void SliderListener() {mediaPlayer.setOnPlaying(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubslider.setMin(0.0);slider.setMax(mediaPlayer.getTotalDuration().toSeconds());mediaPlayer.currentTimeProperty().addListener(new ChangeListener<Duration>() {@Overridepublic void changed(ObservableValue<? extends Duration> observable, Duration oldValue,Duration newValue) {// TODO Auto-generated method stubif(is_mouse==false)slider.setValue(newValue.toSeconds());}});ObservableMap<String, Object> map =media.getMetadata();Image songimage=(Image)map.get("image");ImageView songimageview=new ImageView(songimage);songimageview.setFitWidth(347/2);songimageview.setFitHeight(350/2);song_image.setGraphic(songimageview);song_name.setText(map.get("title").toString());song_name.setFont(new Font("Microsoft Yahei",25));song_name.setStyle("-fx-font-weight: bold;");song_name.setTextFill(Paint.valueOf("#962aec"));song_songer.setText("演唱者:"+map.get("artist").toString());song_songer.setFont(new Font("STHeiti", 15));song_songer.setTextFill(Paint.valueOf("#dd8fe5"));song_type.setText("歌曲类型:"+map.get("genre").toString());song_type.setFont(new Font("STHeiti", 15));song_type.setTextFill(Paint.valueOf("#dd8fe5"));}});
}
public void SetbackgroudAndsongImage() {Image setbackgound=new Image("image/背景副.png");setbackgroud.setGraphic(new ImageView(setbackgound));
}
}
以上就是主界面的全部代码了
下面是数据库的连接工具类
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Dbhelper {private static final String DRIVERNAME="com.mysql.jdbc.Driver";
private static final String URL="jdbc:mysql://localhost:3306/music_library";
private static final String USERNAME="root";
private static final String PASSWORD="123456";
static {try {Class.forName(DRIVERNAME);} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}
}
public static Connection getconnetion() throws SQLException {return DriverManager.getConnection(URL,USERNAME,PASSWORD);
}
public static void close(ResultSet result,PreparedStatement ps,Connection conn) throws SQLException {if(result!=null)result.close();if(ps!=null)ps.close();if(conn!=null)conn.close();
}
}
在调用数据库的连接类得到数据库中的歌曲名字与地址
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;import bean.Music_Bean;
import utils.Dbhelper;public class Music_Dao {//查询public List<Music_Bean> select() throws SQLException{Connection conn=Dbhelper.getconnetion();String sql="SELECT * FROM music";PreparedStatement ps=conn.prepareStatement(sql);ResultSet result=ps.executeQuery();List<Music_Bean> list=new ArrayList<Music_Bean>();while(result.next()) {Music_Bean music=new Music_Bean();music.setId(result.getInt(1));music.setName(result.getString(2));music.setUrl(result.getString(3));list.add(music);}return list;}
}
Music_Bean类
public class Music_Bean {private int id;
private String name;
public String getName() {return name;
}
public void setName(String name) {this.name = name;
}
private String url;
public int getId() {return id;
}
public void setId(int id) {this.id = id;
}
public String getUrl() {return url;
}
public void setUrl(String url) {this.url = url;
}
}
然后这是我自己建立的包
存放歌曲的包
以上就是这个项目的全部代码了
做的不好的地方请各位大神指出,后期我还会对这个播放器添加一下功能
JavaFX简单音乐播放器相关推荐
- Android复习02(ListView具体操作[很详细]、简单音乐播放器)
2020年 3月24日 星期二 Android录播回放 笔记[腾讯课堂] https://ke.qq.com/webcourse/index.html#cid=989760&term_id=1 ...
- 安卓java音乐播放器下一曲_Android实现简单音乐播放器(MediaPlayer)
Android实现简单音乐播放器(MediaPlayer),供大家参考,具体内容如下 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 工程内容 实现一个 ...
- iOS之基于FreeStreamer的简单音乐播放器(模仿QQ音乐)
代码地址如下: http://www.demodashi.com/demo/11944.html 天道酬勤 前言 作为一名iOS开发者,每当使用APP的时候,总难免会情不自禁的去想想,这个怎么做的?该 ...
- java计算机毕业设计vue开发一个简单音乐播放器(附源码、数据库)
java计算机毕业设计vue开发一个简单音乐播放器(附源码.数据库) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Ec ...
- 一个简单音乐播放器的java实现(一)
写在前面 这几天正在读head first系列的书籍,现在正好读的是java.这本书讲的深入浅出,环环相扣,非常精彩,不妨安利给大家,顺便把我学习过程中的一些心得体会已经实例分享出来. 1.一个最简单 ...
- 简单音乐播放器html+css+基础vue+含源码,有搜索和播放mv功能,代码可直接复制用。
题目:html+css+基础vue实现的简单音乐播放器(含源码),有搜索和播放mv功能,代码可直接复制用. 问题描述: 如果vue刚入门,掌握一些基础语法后就可以写一个简单的音乐播放器来练练手~~如果 ...
- android音乐播放器实现,Android实现简单音乐播放器(MediaPlayer)
Android实现简单音乐播放器(MediaPlayer),供大家参考,具体内容如下 开发工具:Andorid Studio 1.3 运行环境:Android 4.4 KitKat 工程内容 实现一个 ...
- C/C++简单音乐播放器系统
C/C++简单音乐播放器系统 程序设计题 1:简单音乐播放器系统 出题人:吴敏 面向专业:计算机科学与技术 难度等级:4 1 问题描述 编写一个简单音乐播放器软件,实现歌单文件的浏览,点歌,加入收藏夹 ...
- C#简单音乐播放器(三)
简单音乐播放器(三) [上一篇]简单音乐播放器(二) 一.前言 时隔一年,终于回来填坑了.前段时间把这个以前写的东西拿出来大改了UI,然后用去作为数字媒体开发课的作业交了,课上演示效果还不错.因为到了 ...
最新文章
- 从find_vma和find_vma_prev看内核
- 国防科技大学发布最新「3D点云深度学习」综述论文
- mac14.5 mojave安装错误
- 【Linux笔记】第七篇、配置MariaDB的字符集
- SAP WebClient UI view controller所有可用的属性列表
- socket 端口和地址复用
- nginx做https跳转apache
- MyBatis学习总结(15)——定制Mybatis自动代码生成的maven插件
- 如何恢复任务栏中的显示桌面图标?
- 上传服务器响应失败,Django CKEditor 上传图片提示“不正确的服务器响应”的解决办法...
- Typescript tsconfig
- C++ string获取字符串元素:[]和at()
- (一)PC 机与单片机通信(RS232 协议)【800个电子设计大赛资料合集】
- 分布式开源调度框架TBSchedule详解
- matlab图例使用技巧
- Win7 开机后3分钟内硬盘等狂闪解决办法
- javaFX 界面例子
- 基于SpringBoot的影视/短视频网站系统
- 以地理国情调查任务为基础的地图矢量化流程研究
- C#中三层架构UI、BLL、DAL、Model实际操作