这篇文章记录了用Swing开发简单的图形用户界面程序与MySQL数据库进行连接,并进行数据获取、数据处理(分页显示)和数据查找的过程
示例程序:
这篇文章是在上篇文章的基础上进行改进和扩充的,因此会时不时地用到上篇文章的代码。
- 准备工作
将上篇文章中Studnet类再次利用,因此我原封不动地搬运过来
public class Student {
private int id;
private String name;
private String sex;
private int age;
public Student(){
this.id=0;
this.name=null;
this.sex=null;
this.age=0;
}
public void setId(int id) {
this.id=id;
}
public int getId() {
return(id);
}
public void setName(String name) {
this.name=name;
}
public String getName() {
return(name);
}
public void setSex(String sex) {
this.sex=sex;
}
public String getSex() {
return(sex);
}
public void setAge(int age) {
this.age=age;
}
public int getAge() {
return(age);
}
}
再对数据管理器类进行如下修改
这里先给出数据管理器类完整代码,然后对修改部分进行解释
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import java.sql.Connection;
public class DBManager {
//四个关键参数
private String driver = "java.sql.Driver";
private String url = "jdbc:mysql://localhost:3306/zijeak";//数据库链接方式:jtbc方式,3306为端口号,最后一项为数据库名
private String uname = "root";
private String password = "root";
private Connection con = null;//数据库链接对象
private Statement sta = null;
private PreparedStatement psta = null;
private ResultSet rs = null;
public DBManager(){
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("驱动加载异常");
}
try{
con = DriverManager.getConnection(url, uname, password);
System.out.println("数据库链接成功");
}catch(SQLException e){
e.printStackTrace();
System.out.println("数据库链接异常");
}
}
//获取全部数据
public void selectTable(Vector<Student> stu) {
String sql = "select * from table01";
try {
sta = con.createStatement();//利用连接器创建语句
rs = sta.executeQuery(sql);
//将语句发送到数据库,返回数据,rs相当于游标指针,可用next()方法访问下一条数据,若有数据返回ture,若无数据返回false
while(rs.next()) {
Student student = new Student();
int id = rs.getInt("ID");
String name = rs.getString("NAME");
String sex = rs.getString("SEX");
int age = rs.getInt("AGE");
//存储到对象
student.setId(id);
student.setName(name);
student.setSex(sex);
student.setAge(age);
stu.add(student);
System.out.println("学号:"+id+" 姓名:"+name+" 性别:"+sex+" 年龄:"+age);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//信息检索
int count=0;
public int selectTable(String sql,Vector<Object> vct) {
Vector<Student> stu_back = new Vector<Student>();
try {
psta = con.prepareStatement(sql);
if(vct!=null) {
for(int i=0;i<vct.size();i++) {
psta.setObject(i+1,vct.get(i));
}
}
rs = psta.executeQuery();
while(rs.next()) {
Student stu = new Student();
int id = rs.getInt("ID");
String name = rs.getString("NAME");
String sex = rs.getString("SEX");
int age = rs.getInt("AGE");
stu.setId(id);
stu.setName(name);
stu.setSex(sex);
stu.setAge(age);
stu_back.add(stu);
System.out.println("学号:"+id+" 姓名:"+name+" 性别:"+sex+" 年龄:"+age);
count++;
}
//若找到搜索结果,显示搜索结果窗口
if(count>=1) {
ShowResult show = new ShowResult(stu_back);
}
} catch (SQLException e) {
e.printStackTrace();
}
return count;
}
public void MyClose(){
try {
if(con!=null){
con.close();
}
if(psta!=null){
psta.close();
}
if(rs!=null){
rs.close();
}
} catch (Exception e) {
}
}
修改部分如下
*修改了查询方法的参数
由于原本的代码只是将查询到信息打印到控制台上,并未存储,因此需要进行修改。
从外部传入一个Vector类的数组,用于将查询到的学生信息全部存储起来,进而图形用户界面的表格控件便可以获取到信息。
public void selectTable(Vector<Student> stu)
stu.add(student);
试用重载方法进行信息检索查询
对方法头做以如下修改
传入的参数多了sql语句,实际上是方法中的sql半成品语句的补足部分,由用户在图形用户界面的搜索框中以字符串形式给出,并设置事件监听。
int count=0;
public int selectTable(String sql,Vector<Object> vct) {
Vector<Student> stu_back = new Vector<Student>();
设置变量count的目的是记录查找到的信息个数,若不为0,则显示检索结果窗口。
代码中的ShowReslut是一个图形用户界面窗口类,下文会进行介绍。
if(count>=1) {
ShowResult show = new ShowResult(stu_back);
}
- 编写主用户界面
先给出完整代码
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javafx.scene.layout.HBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import java.util.Vector;
public class Search {
int countPage=0;//翻页动作中用于记录翻过的页数
public Search() {
JFrame frame = new JFrame();
Container contentPane = frame.getContentPane();
frame.setLocation(400,100);
frame.setSize(1000,700);
//新建JPanel
JPanel jPanel = new JPanel();
Image imageBackgroundTop=new ImageIcon("back.jpg").getImage();
BackgroundPanel jPanelTop = new BackgroundPanel(imageBackgroundTop);
Image imageBackgroundBottom=new ImageIcon("back.jpg").getImage();
BackgroundPanel jPanelBottom = new BackgroundPanel(imageBackgroundBottom);
// 创建一个水平箱容器
Box hBox1 = Box.createHorizontalBox();
Box hBox2 = Box.createHorizontalBox();
// 创建一个垂直箱容器
Box vBox = Box.createVerticalBox();
vBox.add(hBox1);
vBox.add(hBox2);
BorderLayout pane = new BorderLayout();
contentPane.add(jPanelTop,BorderLayout.NORTH);
contentPane.add(jPanelBottom,BorderLayout.SOUTH);
contentPane.add(jPanel,BorderLayout.CENTER);
//jPanel1.setPreferredSize(new Dimension(300, 300));
//新建JLabel
ImageIcon imageIcon = new ImageIcon("logo-w.png");
JLabel label = new JLabel(imageIcon,SwingConstants.CENTER);
jPanelTop.add(vBox);
hBox1.add(label);
//搜索文本框
JTextField textField = new JTextField(50);
//搜索按钮
ImageIcon searchIcon = new ImageIcon("search.png");
JButton searchButton = new JButton(searchIcon);
//searchButton.setContentAreaFilled(false);
searchButton.setBackground(Color.WHITE);
hBox2.add(textField);
hBox2.add(searchButton);
//创建数据管理器实例,并调用查看数据方法
DBManager db = new DBManager();
Vector<Student> stu = new Vector<Student>();
db.selectTable(stu);
//获取二维数组的数据
Object[][] tableData = new Object[10][4];
for(int i=0;i<10;i++) {
for(int j=0;j<4;j++) {
tableData[i][0]=stu.get(i).getId();
tableData[i][1]=stu.get(i).getName();
tableData[i][2]=stu.get(i).getSex();
tableData[i][3]=stu.get(i).getAge();
}
}
//定义一维数据作为列标题
Object[] columnTitle = {"ID" , "NAME" , "SEX","AGE"};
JTable table = new JTable(tableData, columnTitle); // 用双数组创建Table对象
JTableHeader head = table.getTableHeader(); // 创建表格标题对象
head.setPreferredSize(new Dimension(head.getWidth(), 25));// 设置表头大小
head.setFont(new Font("黑体",Font.HANGING_BASELINE,20));
JScrollPane scrollPane = new JScrollPane(table);
//table = new JTable(tableData , columnTitle);
table.setFont(new Font("仿宋", Font.PLAIN, 20));
table.setRowHeight(50);
table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);// 以下设置表格列宽
for (int i = 0; i < 4; i++) {
TableColumn column = table.getColumnModel().getColumn(i);
if (i == 0) {
column.setPreferredWidth(200);
}
if(i!=0) {
column.setPreferredWidth(300);
}
}
jPanel.add(new JScrollPane(table,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
jPanel.setBackground(Color.white);
jPanelBottom.setBackground(Color.BLACK);
//翻页按钮
ImageIcon nextIcon = new ImageIcon("next.png");
JButton next = new JButton(nextIcon);
next.setContentAreaFilled(false);
next.setBackground(Color.white);
ImageIcon backIcon = new ImageIcon("goback.png");
JButton back = new JButton(backIcon);
back.setContentAreaFilled(false);
back.setBackground(Color.white);
Box hBox3 = Box.createHorizontalBox();
hBox3.add(back);
hBox3.add(next);
jPanelBottom.add(hBox3);
//翻页按钮动作
class nextListener extends MouseAdapter{
@Override
public void mouseClicked(MouseEvent e){
JButton jbt = (JButton)e.getSource();
int page=0;//总页数
//每页显示10条数据
if(stu.size()%10==0) {
page = stu.size()/10;
}else {
page = stu.size()/10+1;
}
if(countPage<page) {
countPage++;
}
if(countPage==page) {
JOptionPane failMessage = new JOptionPane();
JOptionPane.showMessageDialog(failMessage,"没有下一页啦!" , "提示",JOptionPane.INFORMATION_MESSAGE);;
}
else {
for(int i=countPage*10;i<(countPage+1)*10;i++) {
for(int j=0;j<4;j++) {
tableData[i-countPage*10][0]=stu.get(i).getId();
tableData[i-countPage*10][1]=stu.get(i).getName();
tableData[i-countPage*10][2]=stu.get(i).getSex();
tableData[i-countPage*10][3]=stu.get(i).getAge();
}
}
}
}
}
next.setActionCommand("next");
next.addMouseListener(new nextListener());
class backListener extends MouseAdapter{
@Override
public void mouseClicked(MouseEvent e){
JButton jbt = (JButton)e.getSource();
int page = stu.size()/10;
countPage--;
if(countPage<0) {//如果当前页是第一页
JOptionPane failMessage = new JOptionPane();
JOptionPane.showMessageDialog(failMessage,"已经是第一页啦!" , "提示",JOptionPane.INFORMATION_MESSAGE);;
countPage=0;
}
else {
for(int i=(countPage)*10;i<(countPage+1)*10;i++) {//(countPage-1)*10;i<countPage*10
for(int j=0;j<4;j++) {
tableData[i][0]=stu.get(i).getId();
tableData[i][1]=stu.get(i).getName();
tableData[i][2]=stu.get(i).getSex();
tableData[i][3]=stu.get(i).getAge();
}
}
}
}
}
back.setActionCommand("back");
back.addMouseListener(new backListener());
//搜索按钮动作
searchButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
searchButton.setActionCommand(textField.getText());
System.out.println("搜索框监听成功: " + textField.getText());
searchButton.addMouseListener(new SearchListener());
}
});
System.out.println(textField.getText());
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setTitle("众里寻他");
frame.setIconImage(searchIcon.getImage());
frame.setVisible(true);
run(table);
}
public void run(JTable table) {
while (true) {
//每隔1秒钟更新JTable
table.validate();
table.updateUI();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//搜索按钮事件监听器
public class SearchListener extends MouseAdapter{
@Override
public void mouseClicked(MouseEvent e) {
JButton jbt = (JButton)e.getSource();//获取事件源
String str = jbt.getActionCommand();//返回事件源名称
String sql = "select * from table01 where NAME=?";//半成品语句
Vector<Object> vct = new Vector<Object>();
vct.add(str);
int count=0;
DBManager db = new DBManager();
count=db.selectTable(sql,vct);
if(count==0) {
JOptionPane failMessage = new JOptionPane();
JOptionPane.showMessageDialog(failMessage,"未能找到相关信息,请确认后重新查找!" , "提示",JOptionPane.INFORMATION_MESSAGE);;
}
}
}
public static void main(String[] args) {
new Search();
}
}
这里使用JFrame来显示主窗口
注意,JFrame默认布局为BorderLayerout,默认布局会屏蔽掉我们的设置大小的方法(如setSize),可以使用setPreferredSize更改大小。
主窗口的结构如下图
代码中,将搜索按钮的事件监听器定义在主类外,作为一个独立类出现。而“下一页”、“上一页”按钮的事件监听器作为内部类出现。
注意还需给出关于页数的判断,否则会出现数组越界异常
为使程序功能完善,需要加入错误提示,例如
if(countPage<0) {//如果当前页是第一页
JOptionPane failMessage = new JOptionPane();
JOptionPane.showMessageDialog(failMessage,"已经是第一页啦!" , "提示",JOptionPane.INFORMATION_MESSAGE);;
countPage=0;
}
count=db.selectTable(sql,vct);
if(count==0) {
JOptionPane failMessage = new JOptionPane();
JOptionPane.showMessageDialog(failMessage,"未能找到相关信息,请确认后重新查找!" , "提示",JOptionPane.INFORMATION_MESSAGE);;
}
if(countPage==page) {
JOptionPane failMessage = new JOptionPane();
JOptionPane.showMessageDialog(failMessage,"没有下一页啦!" , "提示",JOptionPane.INFORMATION_MESSAGE);;
}
需要注意的是:JTable组件内的内容默认不能实时刷新,需要人工设置,否则点击“下一页”、“上一页”会出现部分数据更新的情况,,需要鼠标点击一个个的数据项才可以更新。
为此,加入以下代码:
public void run(JTable table) {
while (true) {
//每隔1秒钟更新JTable
table.validate();
table.updateUI();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
对于搜索结果页,为方便起见,仅对主界面代码进行简单修改即可使用。
代码如下:
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javafx.scene.layout.HBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import java.util.Vector;
public class ShowResult {
public ShowResult(Vector<Student> stu) {
JFrame frame = new JFrame();
Container contentPane = frame.getContentPane();
frame.setLocation(500,200);
frame.setSize(1000,700);
//新建JPanel
JPanel jPanel = new JPanel();
Image imageBackgroundTop=new ImageIcon("background-02.jpg").getImage();
BackgroundPanel jPanelTop = new BackgroundPanel(imageBackgroundTop);
Image imageBackgroundBottom=new ImageIcon("background-02.jpg").getImage();
BackgroundPanel jPanelBottom = new BackgroundPanel(imageBackgroundBottom);
// 创建一个水平箱容器
Box hBox1 = Box.createHorizontalBox();
Box hBox2 = Box.createHorizontalBox();
// 创建一个垂直箱容器
Box vBox = Box.createVerticalBox();
vBox.add(hBox1);
vBox.add(hBox2);
BorderLayout pane = new BorderLayout();
contentPane.add(jPanelTop,BorderLayout.NORTH);
contentPane.add(jPanelBottom,BorderLayout.SOUTH);
contentPane.add(jPanel,BorderLayout.CENTER);
//jPanel1.setPreferredSize(new Dimension(300, 300));
//新建JLabel
ImageIcon imageIcon = new ImageIcon("found.png");
JLabel label = new JLabel(imageIcon,SwingConstants.CENTER);
jPanelTop.add(vBox);
hBox1.add(label);
//搜索文本框
JTextField textField = new JTextField(50);
//搜索按钮
ImageIcon searchIcon = new ImageIcon("search.png");
JButton searchButton = new JButton(searchIcon);
//searchButton.setContentAreaFilled(false);
searchButton.setBackground(Color.WHITE);
//hBox2.add(textField);
//hBox2.add(searchButton);
//获取二维数组的数据
Object[][] tableData = new Object[stu.size()][4];
for(int i=0;i<stu.size();i++) {
for(int j=0;j<4;j++) {
tableData[i][0]=stu.get(i).getId();
tableData[i][1]=stu.get(i).getName();
tableData[i][2]=stu.get(i).getSex();
tableData[i][3]=stu.get(i).getAge();
}
}
//定义一维数据作为列标题
Object[] columnTitle = {"ID" , "NAME" , "SEX","AGE"};
JTable table = new JTable(tableData, columnTitle); // 用双数组创建Table对象
JTableHeader head = table.getTableHeader(); // 创建表格标题对象
head.setPreferredSize(new Dimension(head.getWidth(), 25));// 设置表头大小
head.setFont(new Font("仿宋",Font.PLAIN,20));
JScrollPane scrollPane = new JScrollPane(table);
//table = new JTable(tableData , columnTitle);
table.setFont(new Font("楷体", Font.PLAIN, 18));
table.setRowHeight(50);
table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);// 以下设置表格列宽
for (int i = 0; i < 3; i++) {
TableColumn column = table.getColumnModel().getColumn(i);
if (i == 0) {
column.setPreferredWidth(200);
}
if(i!=0) {
column.setPreferredWidth(300);
}
}
jPanel.add(new JScrollPane(table,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
jPanel.setBackground(Color.white);
jPanelBottom.setBackground(Color.BLACK);
//翻页按钮
ImageIcon nextIcon = new ImageIcon("next.png");
JButton next = new JButton(nextIcon);
next.setContentAreaFilled(false);
next.setBackground(Color.white);
ImageIcon backIcon = new ImageIcon("goback.png");
JButton back = new JButton(backIcon);
back.setContentAreaFilled(false);
back.setBackground(Color.white);
Box hBox3 = Box.createHorizontalBox();
hBox3.add(back);
hBox3.add(next);
jPanelBottom.add(hBox3);
//jPanelBottom.add(next);
frame.setTitle("搜索结果页——众里找到他");
frame.setIconImage(searchIcon.getImage());
frame.setVisible(true);
}
}
- 界面优化
可自行设计界面背景图片,字体格式等
为设置JPanel的背景图片,可以在以下类中实现
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;
public class BackgroundPanel extends JPanel {
/**
*
*/
private static final long serialVersionUID = -6352788025440244338L;
private Image image = null;
public BackgroundPanel(Image image) {
this.image = image;
}
protected void paintComponent(Graphics g) {
g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), this);
}
}
加入自己的个性化设计后,就可以啦~
美化后的效果如图所示
主界面
搜索结果