当前位置:   article > 正文

java上位机开发(GUI设计)_上位机做gui

上位机做gui

 【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        对于上位机来说,GUI设计是很重要的一个环节。如果没有GUI,那就成了命令行工具了。对于java来说,图形库主要有swing和awt两种,选择哪一种可以根据个人的喜好进行选择,差别不大。另外,和大多数图形库一样,java图形库也提供了label、edit、button、dialog、menu这些常用控件。如果是不太常用的控件,那就需要自己绘制了。

        这里我们选择awt进行开发。当然,选好了控件库之后,下面就是设计自己的上位机界面了。一般来说,设计的原则就是简单、有效,不必过于花哨。一来没有必要,二来过度设计往往会导致程序的不稳定。此外,界面设计部分,最好用一些设计工具来做正向设计。它的好处就是方便自己从整体来根据客户的需求做程序交互设计。这里,不妨以一个简单的上位机程序作为背景,来描述应该怎么设计图形界面。

1、GUI设计

        假设我们的需求就是给开发板发一个任务,然后定时检测这个任务的状态。拿到这个需求的时候,正常情况下,想一想应该怎么设计?

         这是程序的主界面,从布局上看比较简洁。第一行是标题;第二行是菜单;中间分成两部分,一部分是Task工作区域,一部分是日志打印区域。最后一行是状态栏。每增加一个Task,就会增加相应的Task条目。执行结束后,Task条目会被删除。在task执行的过程中,不管执行顺利与否,都会在log中间添加相应的打印信息。这个时候,如果需要添加Task,应该怎么设计?单击Menu,就会弹出对应的对话框,如下图所示,

         对话框的内容比较简单,图中仅仅描述了TaskID和TaskName这两个属性。实际情况可以根据具体业务灵活做出选择。所有属性编写结束后,就可以按下ok按钮。如果不希望执行Task,按下Cancel退出即可。

        在执行的过程中,退出程序也是可以的。但是,在程序退出前,必须给出对应的告警信息,这也是常规的操作,

2、程序编写部分

2.1 构建基本窗口

        在熟悉awt之前,第一步应该就是编写最简单的界面程序,增加一点自己的信心。比如这样,

  1. import java.awt.*;
  2. public class process
  3. {
  4. public static void main(String[] args) {
  5. Frame frm = new Frame("Application");
  6. frm.setSize(600, 400);
  7. frm.setVisible(true);
  8. }
  9. }

        经过之前的java基础,这部分内容是可以自己搞明白的。直接输入编译命令,即javac process.java && java process,你就会看到这样的图形,

        虽然对话框里面什么也没有,但是好歹走出了第一步。美中不足的是,这个窗口没有办法关闭,只能自己ctrl+c来解决,这部分确实不太合理,接着我们就会修改一下。

2.2、添加关闭窗口功能

        要做到窗口可以正常关闭,本质上还是添加一个事件响应函数,比如像这样,

  1. import java.awt.*;
  2. import java.awt.event.WindowAdapter;
  3. import java.awt.event.WindowEvent;
  4. public class process
  5. {
  6. public static void main(String[] args) {
  7. Frame frm = new Frame("Application");
  8. frm.setSize(600, 400);
  9. frm.addWindowListener(new WindowAdapter() {
  10. @Override
  11. public void windowClosing(WindowEvent e)
  12. {
  13. System.exit(0);
  14. }
  15. });
  16. frm.setVisible(true);
  17. }
  18. }

        有了这个响应函数,就可以正常关闭窗口了。

2.3 添加label

        添加标签是最基本的动作,可以很容易地完成。

  1. import java.awt.*;
  2. import java.awt.event.WindowAdapter;
  3. import java.awt.event.WindowEvent;
  4. public class process
  5. {
  6. static Label notification = new Label("Are you sure to leave?", Label.CENTER);
  7. public static void main(String[] args) {
  8. Frame frm = new Frame("Application");
  9. frm.setSize(600, 400);
  10. frm.addWindowListener(new WindowAdapter() {
  11. @Override
  12. public void windowClosing(WindowEvent e)
  13. {
  14. System.exit(0);
  15. }
  16. });
  17. frm.add(notification);
  18. frm.setVisible(true);
  19. }
  20. }

        这里添加了一个notification的label,编译后,执行的结果是这样的,

2.4 添加按钮

        label的部分是比较容易。有了label的第一步操作,下面就是添加按钮,

  1. import java.awt.*;
  2. import java.awt.event.WindowAdapter;
  3. import java.awt.event.WindowEvent;
  4. public class process
  5. {
  6. static Label notification = new Label("Are you sure to leave?");
  7. static Button ok_btn = new Button("OK");
  8. static Button cancel_btn = new Button("Cancel");
  9. public static void main(String[] args) {
  10. Frame frm = new Frame("Application");
  11. frm.setLayout(null);
  12. frm.setSize(600, 400);
  13. frm.addWindowListener(new WindowAdapter() {
  14. @Override
  15. public void windowClosing(WindowEvent e)
  16. {
  17. System.exit(0);
  18. }
  19. });
  20. notification.setBounds(225, 100, 200, 100);
  21. frm.add(notification);
  22. ok_btn.setBounds(100, 250, 100, 50);
  23. frm.add(ok_btn);
  24. cancel_btn.setBounds(350, 250, 100, 50);
  25. frm.add(cancel_btn);
  26. frm.setVisible(true);
  27. }
  28. }

        观察发现,除了之前的label,这里还添加了两个按钮,一个是ok_btn,另外一个是cancel_btn。在开始添加控件之前,需要将frame的layout设置为null。接着在添加控件的时候,需要设置下每个控件的大小、范围。这样,经过代码修改后,就可以得到一个合适的布局图形,效果是这样的,

         从布局来看,显然是达到了我们的设计要求,只是看上去不太美观。接下来,就是要对按钮添加响应回调函数。

2.5 按钮回调函数

        按钮的回调函数,本质上还是需要添加一个listener,这和窗口的回调函数,本质上说是一样的。接着我们就编写一个按钮回调函数,

  1. import java.awt.*;
  2. import java.awt.event.*;
  3. public class process
  4. {
  5. static Label notification = new Label("Are you sure to leave?");
  6. static Button ok_btn = new Button("OK");
  7. static Button cancel_btn = new Button("Cancel");
  8. static class myListener implements ActionListener {
  9. public void actionPerformed(ActionEvent e) {
  10. String str = e.getActionCommand();
  11. if (str.equals("OK")){
  12. System.out.println("You choose to leave current dialog!");
  13. System.exit(0);
  14. }
  15. }
  16. }
  17. public static void main(String[] args) {
  18. Frame frm = new Frame("Application");
  19. frm.setLayout(null);
  20. frm.setSize(600, 400);
  21. frm.addWindowListener(new WindowAdapter() {
  22. @Override
  23. public void windowClosing(WindowEvent e)
  24. {
  25. System.exit(0);
  26. }
  27. });
  28. notification.setBounds(225, 100, 200, 100);
  29. frm.add(notification);
  30. ok_btn.setBounds(100, 250, 100, 50);
  31. ok_btn.addActionListener(new myListener());
  32. frm.add(ok_btn);
  33. cancel_btn.setBounds(350, 250, 100, 50);
  34. frm.add(cancel_btn);
  35. frm.setVisible(true);
  36. }
  37. }

        注意,这里添加了一个myListener,它从ActionListener继承而来。为了使用这个基类,import部分也要做一下修改,即从java.awt.event.WindowEvent;变成java.awt.event.*。类中的函数,需要改写的部分就是actionPerformed,判断一下是不是ok按钮,如果是,先打印一些内容,接着就是退出。

2.6 添加edit

        有了label和button的经验,添加edit编辑框就变得不是那么复杂了。

  1. import java.awt.*;
  2. import java.awt.event.*;
  3. public class process
  4. {
  5. static Label label1 = new Label("TaskID:");
  6. static Label label2 = new Label("TaskName:");
  7. static TextField txt1 = new TextField("");
  8. static TextField txt2 = new TextField("");
  9. static Button ok_btn = new Button("OK");
  10. static Button cancel_btn = new Button("Cancel");
  11. static class myListener implements ActionListener {
  12. public void actionPerformed(ActionEvent e) {
  13. String str = e.getActionCommand();
  14. if (str.equals("OK")){
  15. System.out.println("You choose to leave current dialog!");
  16. System.exit(0);
  17. }
  18. }
  19. }
  20. public static void main(String[] args) {
  21. Frame frm = new Frame("Application");
  22. frm.setLayout(null);
  23. frm.setSize(600, 400);
  24. frm.addWindowListener(new WindowAdapter() {
  25. @Override
  26. public void windowClosing(WindowEvent e)
  27. {
  28. System.exit(0);
  29. }
  30. });
  31. label1.setBounds(100, 100, 100, 50);
  32. frm.add(label1);
  33. label2.setBounds(100, 150, 100, 50);
  34. frm.add(label2);
  35. txt1.setBounds(250, 100, 200, 30);
  36. frm.add(txt1);
  37. txt2.setBounds(250, 150, 200, 30);
  38. frm.add(txt2);
  39. ok_btn.setBounds(100, 250, 100, 50);
  40. ok_btn.addActionListener(new myListener());
  41. frm.add(ok_btn);
  42. cancel_btn.setBounds(350, 250, 100, 50);
  43. frm.add(cancel_btn);
  44. frm.setVisible(true);
  45. }
  46. }

        还是在之前的代码基础上,我们添加了txt1和txt2两个编辑框。除此之外,还调整了label1、label2、txt1、txt2的位置,其他的部分几乎没有做什么调整。编译运行后的结果是这样的,

         从布局上看,基本上是达到了设计的目的。

2.7 菜单的添加

        菜单栏一般是主窗口需要的。对于二级窗口,也就是任务窗口、告警提示窗口,这个菜单一般是不需要的。当然,为了展示的需要,我们可以看一下菜单栏是怎么添加的。

  1. import java.awt.*;
  2. import java.awt.event.*;
  3. public class process
  4. {
  5. static Label label1 = new Label("TaskID:");
  6. static Label label2 = new Label("TaskName:");
  7. static TextField txt1 = new TextField("");
  8. static TextField txt2 = new TextField("");
  9. static Button ok_btn = new Button("OK");
  10. static Button cancel_btn = new Button("Cancel");
  11. static MenuBar mb = new MenuBar();
  12. static Menu menu1 = new Menu("Task");
  13. static MenuItem mitem = new MenuItem("New");
  14. static class myListener implements ActionListener {
  15. public void actionPerformed(ActionEvent e) {
  16. String str = e.getActionCommand();
  17. if (str.equals("OK")){
  18. System.out.println("You choose to leave current dialog!");
  19. System.exit(0);
  20. }
  21. }
  22. }
  23. public static void main(String[] args) {
  24. Frame frm = new Frame("Application");
  25. frm.setLayout(null);
  26. frm.setSize(600, 400);
  27. frm.addWindowListener(new WindowAdapter() {
  28. @Override
  29. public void windowClosing(WindowEvent e)
  30. {
  31. System.exit(0);
  32. }
  33. });
  34. menu1.add(mitem);
  35. mb.add(menu1);
  36. frm.setMenuBar(mb);
  37. label1.setBounds(100, 100, 100, 50);
  38. frm.add(label1);
  39. label2.setBounds(100, 150, 100, 50);
  40. frm.add(label2);
  41. txt1.setBounds(250, 100, 200, 30);
  42. frm.add(txt1);
  43. txt2.setBounds(250, 150, 200, 30);
  44. frm.add(txt2);
  45. ok_btn.setBounds(100, 250, 100, 50);
  46. ok_btn.addActionListener(new myListener());
  47. frm.add(ok_btn);
  48. cancel_btn.setBounds(350, 250, 100, 50);
  49. frm.add(cancel_btn);
  50. frm.setVisible(true);
  51. }
  52. }

        从代码上面来看,按钮的添加主要涉及到三个变量。一个是MenuBar,一个是Menu,一个是MenuItem。MenuBar类相当于整个menu的管家,Menu类代表是一级menu,而MenuItem类相当于二级menu,整个逻辑就是这么一回事。编译运行后,整个程序是这么一个效果,

         从一开始的差不多10行代码,走到现在这一步,基本上就有点意思了。整个程序也开始有了软件的味道。这个时候,不要停,我们继续添加状态栏。

2.8 状态栏的添加

        状态栏一般位于窗口的最下方,表示的方法很多,一个比较简单的办法就是用label代替。打上必要的label内容之后,再添加一个灰色的背景,这样就可以做成一个简单的状态栏了。

  1. import java.awt.*;
  2. import java.awt.event.*;
  3. public class process
  4. {
  5. static Label label1 = new Label("TaskID:");
  6. static Label label2 = new Label("TaskName:");
  7. static TextField txt1 = new TextField("");
  8. static TextField txt2 = new TextField("");
  9. static Button ok_btn = new Button("OK");
  10. static Button cancel_btn = new Button("Cancel");
  11. static MenuBar mb = new MenuBar();
  12. static Menu menu1 = new Menu("Task");
  13. static MenuItem mitem = new MenuItem("New");
  14. static Label label_status = new Label(" 2022/7/10 ");
  15. static class myListener implements ActionListener {
  16. public void actionPerformed(ActionEvent e) {
  17. String str = e.getActionCommand();
  18. if (str.equals("OK")){
  19. System.out.println("You choose to leave current dialog!");
  20. System.exit(0);
  21. }
  22. }
  23. }
  24. public static void main(String[] args) {
  25. Frame frm = new Frame("Application");
  26. frm.setLayout(null);
  27. frm.setSize(600, 400);
  28. frm.addWindowListener(new WindowAdapter() {
  29. @Override
  30. public void windowClosing(WindowEvent e)
  31. {
  32. System.exit(0);
  33. }
  34. });
  35. menu1.add(mitem);
  36. mb.add(menu1);
  37. frm.setMenuBar(mb);
  38. label1.setBounds(100, 100, 100, 50);
  39. frm.add(label1);
  40. label2.setBounds(100, 150, 100, 50);
  41. frm.add(label2);
  42. txt1.setBounds(250, 100, 200, 30);
  43. frm.add(txt1);
  44. txt2.setBounds(250, 150, 200, 30);
  45. frm.add(txt2);
  46. ok_btn.setBounds(100, 250, 100, 50);
  47. ok_btn.addActionListener(new myListener());
  48. frm.add(ok_btn);
  49. cancel_btn.setBounds(350, 250, 100, 50);
  50. frm.add(cancel_btn);
  51. label_status.setBounds(0, 355, 600, 35);
  52. label_status.setBackground(Color.gray);
  53. frm.add(label_status);
  54. frm.setVisible(true);
  55. }
  56. }

        如图所示,这里的label_status就是状态栏,它的作用就是显示一些任务的必要信息。比如已经执行了多少任务,多少任务成功,多少任务失败等等。编译,执行查看一下运行效果,

2.9 表格的添加

        之前在设计的时候,对于运行中单个Task的状态,这部分可以用表格来表示。因为之前的代码已经过长,这里我们重新用简单一点的程序来进行说明,

  1. import javax.swing.JFrame;
  2. import javax.swing.JScrollPane;
  3. import javax.swing.JTable;
  4. import javax.swing.table.DefaultTableModel;
  5. import java.awt.BorderLayout;
  6. public class process extends JFrame {
  7. private String[] columns = { "TaskID", "TaskName", "TaskState" };
  8. public process() {
  9. JScrollPane scrollpane = new JScrollPane();
  10. DefaultTableModel model = new DefaultTableModel(columns, 10);
  11. JTable table = new JTable(model);
  12. scrollpane.setViewportView(table);
  13. add(scrollpane, BorderLayout.CENTER);
  14. setSize(600, 400);
  15. setDefaultCloseOperation(EXIT_ON_CLOSE);
  16. setVisible(true);
  17. }
  18. public static void main(String[] args) {
  19. new process();
  20. }
  21. }

        这里面使用了swing的数据结构,最重要的数据类型其实就是DefaultTableModel这个类,它定义了基本的数据结构,包括表格内容,包括表格行数等等。可以简单运行一下,看下效果,

3、总结

        对于GUI设计来说,设计是根本,用什么控件、什么库来实现这个设计,这个是操作层面的事情,关键是作为设计者心里要有一个基本的判断和计划。这个计划包括,主窗口布局是什么,二级窗口做什么,主要的交互逻辑是什么,哪些信息需要显示,哪些信息不需要显示等等。有了这个设计之后,就可以开始着手选用什么控件,从哪里可以找到对应的示例代码,怎么插入到我们的实际应用中去。所以需求是出发点,设计才是根本,编码只是为了把设计做出来、实现出来。

        最后,对于其他控件有兴趣的同学,可以参考一下这个链接,相信会也有不同的收获。

https://www.javagreat.com/awt/https://www.javagreat.com/awt/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/112204
推荐阅读
相关标签
  

闽ICP备14008679号