java上位机开发(Java上位机开发)

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

java上位机开发(Java上位机开发)

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

1、GUI设计

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

java上位机开发(Java上位机开发)

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

java上位机开发(Java上位机开发)

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

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

java上位机开发(Java上位机开发)

2、程序编写部分

2.1 构建基本窗口

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

import java.awt.*; public class process { public static void main(String[] args) { Frame frm = new Frame("Application"); frm.setSize(600, 400); frm.setVisible(true); }}

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

java上位机开发(Java上位机开发)

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

2.2、添加关闭窗口的功能

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

import java.awt.*;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;public class process { public static void main(String[] args) { Frame frm = new Frame("Application"); frm.setSize(600, 400); frm.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); frm.setVisible(true); }}

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

2.3 添加label

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

import java.awt.*;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;public class process { static Label notification = new Label("Are you sure to leave?", Label.CENTER); public static void main(String[] args) { Frame frm = new Frame("Application"); frm.setSize(600, 400); frm.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); frm.add(notification); frm.setVisible(true); }}

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

java上位机开发(Java上位机开发)

2.4 添加按钮

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

import java.awt.*;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;public class process { static Label notification = new Label("Are you sure to leave?"); static Button ok_btn = new Button("OK"); static Button cancel_btn = new Button("Cancel"); public static void main(String[] args) { Frame frm = new Frame("Application"); frm.setLayout(null); frm.setSize(600, 400); frm.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); notification.setBounds(225, 100, 200, 100); frm.add(notification); ok_btn.setBounds(100, 250, 100, 50); frm.add(ok_btn); cancel_btn.setBounds(350, 250, 100, 50); frm.add(cancel_btn); frm.setVisible(true); }}

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

java上位机开发(Java上位机开发)

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

2.5 按钮回调函数

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

import java.awt.*;import java.awt.event.*;public class process { static Label notification = new Label("Are you sure to leave?"); static Button ok_btn = new Button("OK"); static Button cancel_btn = new Button("Cancel"); static class myListener implements ActionListener { public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); if (str.equals("OK")){ System.out.println("You choose to leave current dialog!"); System.exit(0); } } } public static void main(String[] args) { Frame frm = new Frame("Application"); frm.setLayout(null); frm.setSize(600, 400); frm.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); notification.setBounds(225, 100, 200, 100); frm.add(notification); ok_btn.setBounds(100, 250, 100, 50); ok_btn.addActionListener(new myListener()); frm.add(ok_btn); cancel_btn.setBounds(350, 250, 100, 50); frm.add(cancel_btn); frm.setVisible(true); }}

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

2.6 添加edit

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

import java.awt.*;import java.awt.event.*;public class process { static Label label1 = new Label("TaskID:"); static Label label2 = new Label("TaskName:"); static TextField txt1 = new TextField(""); static TextField txt2 = new TextField(""); static Button ok_btn = new Button("OK"); static Button cancel_btn = new Button("Cancel"); static class myListener implements ActionListener { public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); if (str.equals("OK")){ System.out.println("You choose to leave current dialog!"); System.exit(0); } } } public static void main(String[] args) { Frame frm = new Frame("Application"); frm.setLayout(null); frm.setSize(600, 400); frm.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); label1.setBounds(100, 100, 100, 50); frm.add(label1); label2.setBounds(100, 150, 100, 50); frm.add(label2); txt1.setBounds(250, 100, 200, 30); frm.add(txt1); txt2.setBounds(250, 150, 200, 30); frm.add(txt2); ok_btn.setBounds(100, 250, 100, 50); ok_btn.addActionListener(new myListener()); frm.add(ok_btn); cancel_btn.setBounds(350, 250, 100, 50); frm.add(cancel_btn); frm.setVisible(true); }}

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

java上位机开发(Java上位机开发)

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

2.7 菜单的添加

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

import java.awt.*;import java.awt.event.*;public class process { static Label label1 = new Label("TaskID:"); static Label label2 = new Label("TaskName:"); static TextField txt1 = new TextField(""); static TextField txt2 = new TextField(""); static Button ok_btn = new Button("OK"); static Button cancel_btn = new Button("Cancel"); static MenuBar mb = new MenuBar(); static Menu menu1 = new Menu("Task"); static MenuItem mitem = new MenuItem("New"); static class myListener implements ActionListener { public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); if (str.equals("OK")){ System.out.println("You choose to leave current dialog!"); System.exit(0); } } } public static void main(String[] args) { Frame frm = new Frame("Application"); frm.setLayout(null); frm.setSize(600, 400); frm.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); menu1.add(mitem); mb.add(menu1); frm.setMenuBar(mb); label1.setBounds(100, 100, 100, 50); frm.add(label1); label2.setBounds(100, 150, 100, 50); frm.add(label2); txt1.setBounds(250, 100, 200, 30); frm.add(txt1); txt2.setBounds(250, 150, 200, 30); frm.add(txt2); ok_btn.setBounds(100, 250, 100, 50); ok_btn.addActionListener(new myListener()); frm.add(ok_btn); cancel_btn.setBounds(350, 250, 100, 50); frm.add(cancel_btn); frm.setVisible(true); }}

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

java上位机开发(Java上位机开发)

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

2.8 状态栏的添加

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

import java.awt.*;import java.awt.event.*;public class process { static Label label1 = new Label("TaskID:"); static Label label2 = new Label("TaskName:"); static TextField txt1 = new TextField(""); static TextField txt2 = new TextField(""); static Button ok_btn = new Button("OK"); static Button cancel_btn = new Button("Cancel"); static MenuBar mb = new MenuBar(); static Menu menu1 = new Menu("Task"); static MenuItem mitem = new MenuItem("New"); static Label label_status = new Label(" 2022/7/10 "); static class myListener implements ActionListener { public void actionPerformed(ActionEvent e) { String str = e.getActionCommand(); if (str.equals("OK")){ System.out.println("You choose to leave current dialog!"); System.exit(0); } } } public static void main(String[] args) { Frame frm = new Frame("Application"); frm.setLayout(null); frm.setSize(600, 400); frm.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); menu1.add(mitem); mb.add(menu1); frm.setMenuBar(mb); label1.setBounds(100, 100, 100, 50); frm.add(label1); label2.setBounds(100, 150, 100, 50); frm.add(label2); txt1.setBounds(250, 100, 200, 30); frm.add(txt1); txt2.setBounds(250, 150, 200, 30); frm.add(txt2); ok_btn.setBounds(100, 250, 100, 50); ok_btn.addActionListener(new myListener()); frm.add(ok_btn); cancel_btn.setBounds(350, 250, 100, 50); frm.add(cancel_btn); label_status.setBounds(0, 355, 600, 35); label_status.setBackground(Color.gray); frm.add(label_status); frm.setVisible(true); }}

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

java上位机开发(Java上位机开发)

2.9 表格的添加

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

import javax.swing.JFrame;import javax.swing.JScrollPane;import javax.swing.JTable;import javax.swing.table.DefaultTableModel;import java.awt.BorderLayout;public class process extends JFrame { private String[] columns = { "TaskID", "TaskName", "TaskState" }; public process() { JScrollPane scrollpane = new JScrollPane(); DefaultTableModel model = new DefaultTableModel(columns, 10); JTable table = new JTable(model); scrollpane.setViewportView(table); add(scrollpane, BorderLayout.CENTER); setSize(600, 400); setDefaultCloseOperation(EXIT_ON_CLOSE); setVisible(true); } public static void main(String[] args) { new process(); }}

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

java上位机开发(Java上位机开发)

3、总结

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

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

原文链接:https://blog.csdn.net/feixiaoxing/article/details/125702698

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

(0)
上一篇 2024年5月1日 上午8:13
下一篇 2024年5月1日 上午8:25

相关推荐