第1讲 Java图形窗口程序设计

教学与实践目的:回顾、熟悉和掌握Java图形界面的设计及标准输入输出方法,为后续编程任务奠定基础。

说明:在Java体系中,最常用的图形界面设计库主要是Swing和JavaFX,本课程使用JavaFX,采用手写代码方式创建窗体界面,建议的jdk版本为jdk8(因为jdk8已经内置javaFX库,后续版本被剥离,需要额外下载jar包),oc.our-web.org教学资源站点可下载JDK8。

本课程编程使用的IDE建议为Intellij Idea Community(免费版本)。

简单的图形界面程序

图形界面如图1.1所示。

知识点:JavaFX布局,TextFiled、TextArea、Button、Label等各控件用法,事件驱动,字符串读写技术,字符流IO

图1.1 用户界面

该应用程序使用“发送”按钮将信息输入区的内容显示在信息显示区中;“保存”按钮将显示的内容保存到文本文件;“加载”将文本文件内容显示。

1. 窗体界面创建

(1)启动Intellij Idea (以后简称
idea),新建项目之前,首先设置默认的编码为utf-8,如图1.2所示。

图1.2 设置

(2)新建一个项目,如图1.3所示,左方选择“Java”,右方不要勾选任何Additional
Libraries and
Frameworks,按提示一路next,选择一个合适的项目名完成新建过程,例如NetworkApp,在机房上机时,建议在D盘新建一个自己学号的文件夹,然后把项目建立在该文件夹中,方便管理。下课时将自己的项目文件夹打包带走,然后清理掉文件夹。所有的代码也使用package来管理,例如本章可以在src下新建一个包chapter01,这一讲内容的代码就在这个包下来创建。

图1.3 新建项目

(3)
新建javaFX源程序,命名为SimpleFX:鼠标右键点击对应的包chapter01,在弹出菜单中New
-> JavaFXApplication,如图1.4所示,然后命名即可。

图1.4 新建JavaFX源程序

2. 窗体界面相关核心代码

public class SimpleFX extends Application {
private Button btnExit = new Button("退出");
private Button btnSend = new Button("发送");
private Button btnOpen = new Button("加载");
private Button btnSave = new Button("保存");
*//待发送信息的文本框*
private TextField tfSend = new TextField();
*//显示信息的文本区域*
private TextArea taDisplay = new TextArea();  public void start(Stage primaryStage) {
BorderPane mainPane = new BorderPane();
*//内容显示区域*
VBox vBox = new VBox();
vBox.setSpacing(10);*//各控件之间的间隔*
*//VBox面板中的内容距离四周的留空区域*
vBox.setPadding(new Insets(10,20,10,20));
vBox.getChildren().addAll(new Label("信息显示区:"),
taDisplay,new Label("信息输入区:"), tfSend);
*//设置显示信息区的文本区域可以纵向自动扩充范围*
VBox.*setVgrow*(taDisplay, Priority.*ALWAYS*);
mainPane.setCenter(vBox);
*//底部按钮区域*
HBox hBox = new HBox();
hBox.setSpacing(10);
hBox.setPadding(new Insets(10,20,10,20));
hBox.setAlignment(Pos.*CENTER_RIGHT*);
hBox.getChildren().addAll(btnSend,btnSave,btnOpen,btnExit);
mainPane.setBottom(hBox);
Scene scene = new Scene(mainPane,700,400);
primaryStage.setScene(scene);
primaryStage.show();……*//--------事件驱动响应代码部分--------*……
}

对于文本区域taDisplay控件,自行查找方案,将其设置为只读和自动换行。

该程序中,需要对四个按钮的点击操作进行响应,可使用动作事件,即调用按钮的setOnActon方法,如果事件响应的代码量不大,可以直接在方法的参数中写匿名内部类或lambda表达式,否则就单独写一个内部类,其实例作为方法的参数。

对于**“退出”按钮**,代码很简单,使用lambda表达式,其参考代码为:

btnExit.setOnAction(event -\> {System.exit(0);});

“发送”按钮参考代码:

btnSend.setOnAction(event -\> {
String msg = tfSend.getText();
taDisplay.appendText(msg + "\\n");tfSend.clear();
});

请添加文本框tfSend的回车响应功能:文本框中输完内容,回车即可将信息添加到信息显示区;如果是Shift+回车,则在信息前加上
echo: 的信息头再发送。

信息的文件读写

信息的文件读写是指将信息显示区的信息保存到文本文件,或从文本文件中读取内容。

**设计思想:**新增一个文件操作类,完成文件在磁盘方面的读写功能,并对外提供功能接口。保存和读取的文本文件不应该写死在代码中,而是由用户来选择,可以使用文件对话框(JavaFX中的对话框用法,及文本文件的读写类的选择可参看本讲的附录部分)。

知识点: IO操作,文件选择框,异常处理,类之间的调用

1. 实现流程

(1)新增一个文件操作类TextFileIO,负责文件操作的相关功能,至少实现append方法和load方法用于保存和读取文件;

(2)在SimpleFX类中的合适位置将TextFileIO类实例化为textFileIO,在“保存”按钮的响应事件代码中添加相应功能,代码段如下:

btnSave.setOnAction(event -\> {
*//添加当前时间信息进行保存*
textFileIO.append(
LocalDateTime.*now*().withNano(0) +" "+ taDisplay.getText());
});

(3)在“加载”按钮的响应事件代码中添加相应功能,代码段如下:

btnOpen.setOnAction(event -\> {
String msg = textFileIO.load();
if(msg != null){
taDisplay.clear();
taDisplay.setText(msg);
}
});

2. TextFileIO类的核心代码

public class TextFileIO {
private PrintWriter pw = null;
private Scanner sc = null;  public TextFileIO() {
}  public void append(String msg) {
FileChooser fileChooser = new FileChooser();
File file = fileChooser.showSaveDialog(null);
if(file == null) *//用户放弃操作则返回*
return;
*//以追加模式utf-8的编码模式写到文件中*
try {
pw = new PrintWriter(
new OutputStreamWriter(
new FileOutputStream(file, true), "utf-8"));
pw.println(msg);
} catch (Exception e) {
e.printStackTrace();
} finally {
pw.close();
}
}  public String load() {
FileChooser fileChooser = new FileChooser();
File file = fileChooser.showOpenDialog(null);
if(file == null) *//用户放弃操作则返回*
return null;
StringBuilder sb = new StringBuilder();
try {
*//读和写的编码要注意保持一致*
sc = new Scanner(file,"utf-8");
while (sc.hasNext()) {
sb.append(sc.nextLine() + "\\n"); *//补上行读取的行末尾回车*
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sc.close();
}
return sb.toString();
}
}

这个TextFileIO类的设计其实不太合适,这种封装基础操作的类,应该是可以适用于各种场合,而这个类的操作中使用了窗体的对话框方式,在一些无GUI的控制台环境就无法使用了。大家可以思考这个类如何优化,对应的窗体程序又该如何对应修改。

注意事项

我们会看到不少窗体程序例子,控件类型的变量,例如Button、TextFiled等类型变量,是直接定义在start方法中,就是成为局部变量,随用随定义。这种情况是因为所有访问该变量的代码都在这个方法中,例如事件响应代码等。

但从设计考虑,可能被多个方法访问的变量,还是类似本讲的方式,定义为成员变量更方便;对于那些不需要再访问的类型,例如Label,就选择定义为局部变量。

掌握好本讲的窗体布局、事件响应等知识,后续章节的窗体都是本讲类似界面,只要稍作修改即可。

附录

JavaFX中的对话框

在窗体编程中,对话框使用频率很高,Java 8u40
之后JavaFX才内置有对话框功能,参见JavaFX中对话框.pptx,详细用法可参考慕课网中对应内容的视频:第十四讲
JavaFx中其它的知识点 -> 14.1
JavaFX中的对话框(该课程的加入密码为javagdufs)

字节流和字符(文本)流

**字节流:**是8比特一个单元,如键盘输入流、文件输入流、网络输入流,文件输出流、网络输出流等。

支持字节流操作的类有:

OutputStream, FileOutputStream, DataOutputStream 等是字节输出流;

InputStream, FileInputStream, DataInputStream等是字节输入流;

字符流:8/16/32比特一个单元,其长度取决采用何种编码算法,如ISO为32位,GB2312/GBK,utf-8等为16位,ASCII为8位。

支持字符和字符串操作的类有:

InputStreamReader,BufferedReader、Scanner可读字符类,

OutputStreamWriter,PrintWriter可写字符类,

写文本文件最常用的类是PrintWriter,PrintWriter类中有一个常用的println(msg)方法,向输出流中输出一行字符,并自动添加一个行结束符:\n。注意,在使用PrintWriter类时,其虽然可以将文件名作为参数来写文件,但这种用法不能提供追加模式的,所以一般是和FileOutputStream联合使用,例如:

new PrintWriter(new FileOutputStream("temp.txt", true));

如果还需要指定文本的编码,并且是追加模式,可以这样联合使用:

new PrintWriter(new OutputStreamWriter(new FileOutputStream("temp.txt",true), "UTF-8"));

读文件常用的是Scanner和BufferedReader类。Scanner提供了大量对应PrintWriter的写操作的相反的读操作,最常用的是nextLine()方法;而BufferedReader类中有一个常用的readLine()方法,从输入流中读一行字符。

在本地文本文件读写中,常用的字符流组合是PrintWriter和Scanner。在网络信息传输中,常用的字符流组合是PrintWriter和BufferedReader,BufferedReader相对Scanner虽然功能少些,但其效率更高,尤其是在网络传输中。

3. 控制台乱码问题

Windows操作系统中,cmd控制台默认的编码为gbk,一些使用utf-8编码的中文内容在控制台显示就可能出现编码不一致造成的乱码,这种情况下,可以临时将控制台编码修改为utf-8:

(1)运行CMD

(2)在命令行中输入 chcp 65001 回车,
控制台会切换到新的代码页(65001表示utf-8,默认为936)

(3)在标题栏点击右键, 打开属性面板,
会看到“选项”标签页下方显示“当前代码页”的编码. 然后选择“字体”标签页,
把字体设置为Lucia Console, 然后确定关闭.

完整代码实现

SimpleFX

package chapter01;import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;import java.io.File;
import java.time.LocalDateTime;public class SimpleFX extends Application {private Button btnExit = new Button("退出");private Button btnSend = new Button("发送");private Button btnOpen = new Button("加载");private Button btnSave = new Button("保存");//待发送信息的文本框private TextField tfSend = new TextField();//显示信息的文本区域private TextArea taDisplay = new TextArea();private TextFileIO textFileIO = new TextFileIO();public void start(Stage primaryStage) {BorderPane mainPane = new BorderPane();//内容显示区域VBox vBox = new VBox();vBox.setSpacing(10);//各控件之间的间隔//VBox面板中的内容距离四周的留空区域vBox.setPadding(new Insets(10, 20, 10, 20));vBox.getChildren().addAll(new Label("信息显示区:"),taDisplay, new Label("信息输入区:"), tfSend);//设置显示信息区的文本区域可以纵向自动扩充范围VBox.setVgrow(taDisplay, Priority.ALWAYS);mainPane.setCenter(vBox);//底部按钮区域HBox hBox = new HBox();hBox.setSpacing(10);hBox.setPadding(new Insets(10, 20, 10, 20));hBox.setAlignment(Pos.CENTER_RIGHT);hBox.getChildren().addAll(btnSend, btnSave, btnOpen, btnExit);mainPane.setBottom(hBox);Scene scene = new Scene(mainPane, 500, 400);primaryStage.setScene(scene);primaryStage.show();//--------事件驱动响应代码部分--------taDisplay.setEditable(false);taDisplay.setWrapText(true);btnExit.setOnAction(event -> {System.exit(0);});btnSend.setOnAction(event -> {String msg = tfSend.getText();taDisplay.appendText(msg + "\n");tfSend.clear();});tfSend.setOnKeyPressed(new EventHandler<KeyEvent>() {@Overridepublic void handle(KeyEvent event) {if (event.isShiftDown() && event.getCode() == KeyCode.ENTER) {String msg = tfSend.getText();taDisplay.appendText("echo" + msg + "\n");tfSend.clear();} else if (event.getCode() == KeyCode.ENTER) {String msg = tfSend.getText();taDisplay.appendText(msg + "\n");tfSend.clear();}}});btnSave.setOnAction(event -> {FileChooser fileChooser = new FileChooser();File file = fileChooser.showSaveDialog(null);textFileIO.append(file,LocalDateTime.now().withNano(0) + " " + taDisplay.getText());});btnOpen.setOnAction(event -> {FileChooser fileChooser = new FileChooser();File file = fileChooser.showSaveDialog(null);String msg = textFileIO.load(file);if (msg != null) {taDisplay.clear();taDisplay.setText(msg);}});}}

TextFileIO


package chapter01;import javafx.stage.FileChooser;import java.io.*;
import java.util.Scanner;public class TextFileIO {private PrintWriter pw = null;private Scanner sc = null;public  TextFileIO(){}
//    public  void append(String msg) {//        FileChooser fileChooser = new FileChooser();
//        File file = fileChooser.showSaveDialog(null);
//        if (file == null)
//            return;
//        try {//            pw = new PrintWriter(
//                    new OutputStreamWriter(
//                            new FileOutputStream(file, true), "utf-8"));
//            pw.println(msg);
//        } catch (Exception e) {//            e.printStackTrace();
//        } finally {//            pw.close();
//        }
//    }//    public String load(){//            FileChooser fileChooser = new FileChooser();
//            File file = fileChooser.showSaveDialog(null);
//            if(file == null)
//                return null;
//            StringBuilder sb = new StringBuilder();
//            try {//                sc = new Scanner(file,"utf-8");
//                while(sc.hasNext()){//                    sb.append(sc.nextLine()+"\n");
//
//                }
//            } catch (FileNotFoundException e) {//                e.printStackTrace();
//            }finally {//                sc.close();
//            }
//            return sb.toString();
//
//    }// 改写之后,不需要GUI界面的IOpublic  void append(File file,String msg) {if (file == null)return;try {pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file, true), "utf-8"));pw.println(msg);} catch (Exception e) {e.printStackTrace();} finally {pw.close();}}public String load(File file){if(file == null)return null;StringBuilder sb = new StringBuilder();try {sc = new Scanner(file,"utf-8");while(sc.hasNext()){sb.append(sc.nextLine()+"\n");}} catch (FileNotFoundException e) {e.printStackTrace();}finally {sc.close();}return sb.toString();}}

《互联网程序设计》课程:第1讲 JAVA图形窗口程序设计 (完整代码实现)相关推荐

  1. JavaFX实现网络对话程序设计(互联网程序设计课程 第2讲)

    文章目录 简单网络对话程序 1. 程序设计第一步 2. 程序设计第二步 3. 程序设计第三步 4. 建议 扩展 项目结构 完整参考代码 chapter02.TCPClient.java(客户端) ch ...

  2. c语言循环结构程序设计视频,第13讲:循环结构程序设计1

    C语言是计算机科学及应用专业的一门重要的专业基础 课,也是全校各 个专业的公共必修课程.它既可以为其它专业课程奠定程序设计的基础,又可以作为其它专业课程的程序设计的工具. 通过本课程的学习,应掌握计算 ...

  3. 兰州大学C语言程序设计课程作业,【兰州大学|兰州大学C语言程序设计课程作业( 五 )】语言程序设计|课程|作业-傻大方...

    『易坊知识库摘要_兰州大学|兰州大学C语言程序设计课程作业( 五 )』34.用户未作答标准答案exp04. 以下叙述中正确的是 在程序的一行上可以出现多个有效的预处理命令行使用带参的宏时,参数的类型应 ...

  4. java登录注册抽奖完整代码_Java抽奖系统(附完整代码)

    完整代码import java.util.Scanner;import java.util.ArrayList;import java.io.*;import java.util.StringToke ...

  5. java登录注册抽奖完整代码_JAVA实现用户抽奖功能(附完整代码)

    需求分析 1)实现三个基本功能:登录.注册.抽奖. 2)登录:用户输入账号密码进行登录,输入账号后会匹配已注册的用户,若输入用户不存在则退出,密码有三次输入机会,登录成功后主界面会显示已登录用户的账号 ...

  6. 王家林最受欢迎的一站式云计算大数据和移动互联网解决方案课程 V1之Android架构设计和实现完整训练:HALFrameworkNative ServiceAndroid ServiceBes

    如何理解Android架构设计的初心并开发出搭载Android系统并且具备深度定制和软硬整合能力特色产品,是本课程解决的问题. 课程以Android的五大核心:HAL.Binder.NativeSer ...

  7. 王家林最受欢迎的一站式云计算大数据和移动互联网解决方案课程 V1(20140809)之Hadoop企业级完整训练:Rocky的16堂课(HDFSMapReduceHBaseHiveZookee

    Hadoop是云计算的事实标准软件框架,是云计算理念.机制和商业化的具体实现,是整个云计算技术学习中公认的核心和最具有价值内容. 如何从企业级开发实战的角度开始,在实际企业级动手操作中深入浅出并循序渐 ...

  8. c语言程序设计课程设计学生信息管理系统,C语言程序设计课程设计报告----学生信息管理系统.doc...

    河南理工大学计算机学院 <C语言程序设计>课程设计报告 题目: 学生信息管理系统 专业: 计算机科学与技术 班级: 计算机XX班 学号: 311009033232 姓名: ***** 日期 ...

  9. java程序设计简单程序分类_3 Java的基本程序设计结构

    3.1 一个简单的Java应用程序 public classFirstSample {public static voidmain(String[] args) { System.out.printl ...

最新文章

  1. android 停用应用的命令,免Root使用ADB命令_停用手机系统应用
  2. SQLite的Pragma语句
  3. hibernate对象管理
  4. 如何安装,卸载eclipse中的ADT,或者更新ADT
  5. Struts2框架执行流程
  6. “新基建”横空出世,9本书助你把握7+2大领域风口
  7. 我的Android进阶之旅------Android图片处理(Matrix,ColorMatrix)
  8. python123-Python123
  9. GDB 多线程调试:只停止断点的线程,其他线程任然执行; 或只运行某些线程 其他线程中断...
  10. webstorm(10.0.2)设置测试服务器 -- 局域网内其他设备访问
  11. 20200628每日一句
  12. JAVA最全最细基础知识点
  13. gui框架 java_现在选择哪个Java GUI框架
  14. png格式图像转成jpg图像时出现异常颜色值
  15. 个人笔记-如何学习(上)
  16. Excel应用技巧:单元格文字的拆分与合并
  17. Tableau 不同产地电影数量与评分-案例讲解
  18. 清华计算机全球第4!USNews计算机专业排名出炉,67所大陆高校上榜
  19. google hacking常用语法
  20. tar包解压和打包方法

热门文章

  1. 计算机网络基础试卷分析,《计算机应用基础》期末试卷分析.doc
  2. 上海市计算机学会-买二送一
  3. 车道线检测CondLaneNet论文和源码解读
  4. VMware Horizon 8 2209 - 虚拟桌面基础架构 (VDI) 和应用软件
  5. Linux内核中的IPSEC实现(3)
  6. fedora14安装出错
  7. 基于RC电路的DA14585测量NTC电阻阻值
  8. STM32F10xxx20xxx21xxxL1xxxx Cortex-M3程序设计手册 阅读笔记三(1):Cortex-M3指令集概要
  9. Java垃圾回收策略
  10. myeclipse加大内存