QQ登录界面实现(JAVA)
先上图吧,无图无真相。
一、布局
qq登录界面实现和计算器界面实现是一堂课的作业,都是对布局的练习。常用布局模式三种:流式较简单容易掌握;qq登录界面对应边框布局的练习;计算器界面对应网格布局的练习。然而在实际操作中我发现各种布局都有利有弊,对于这种组件较少的小界面来说“无招胜有招”,有时候没有布局反而是最好的布局。直接将布局设置为null,这样对于各组件位置的摆放将会随心所欲了。不过我这个界面还是按照老套路
用的边框布局。
先分析实现qq登录界面各面板的情况:北边面板需要在右上角添加设置、最小化和关闭按钮;西边面板上需要添加qq头像的标签;*面板需要添加下拉框、密码输入框、注册账号和找回密码的标签、记住密码和自动登录的复选框;南边面板需要添加多账号管理按钮、登录按钮、二维码登录按钮。把布局分析好后开始实例化界面、布局。
//定义一个初始化界面的方法
public void initUI(){
jf.setTitle("qq登录界面");//设置窗体的标题
jf.setSize(380, 294);//设置窗体的大小
jf.setLocation(497, 242);//设置窗体的位置
jf.setDefaultCloseOperation(3);//设置关闭时退出程序
jf.setResizable(true);//设置不能调整窗口大小
addBackgroundImage(jf);
//实例化一个边框布局
BorderLayout bl = new BorderLayout();
//设置窗体的布局为边框布局
jf.setLayout(bl);
/*********北边的面板容器*************/
JPanel PanelNorth = creatPanelNorth();
jf.add(PanelNorth,bl.NORTH);
/*********西边的面板容器*************/
JPanel PanelWest = creatPanelWest();
jf.add(PanelWest,bl.WEST);
/*********中间的面板容器*************/
JPanel PanelCenter = creatPanelCenter();
jf.add(PanelCenter);
/*********南边的面板容器*************/
JPanel PanelSouth = creatPanelSouth();
jf.add(PanelSouth,bl.SOUTH);
jf.setUndecorated(true);//消除边框
jf.setVisible(true);//设置窗体是否可见
Graphics g=jpin.getGraphics();
}
如果没有消除边框将会有系统自带的边框,效果如下:
二、背景添加及各图片源文件获取
添加背景方法的代码:
//定义一个添加背景的方法
public void addBackgroundImage(JFrame jf){
//实例化一个ImageIcon图标类的对象
ImageIcon image = new ImageIcon("afternoon.jpg");
//实例化一个标签类的对象
JLabel background = new JLabel(image);
//设置标签显示的位置和大小
background.setBounds(0,0,image.getIconWidth(),image.getIconHeight());
//将标签添加到窗体的第二层面板上
jf.getLayeredPane().add(background,new Integer(Integer.MIN_VALUE));
//获取窗体的第一层板对象
JPanel contentPanel = (JPanel)jf.getContentPane();
//设置第一层面板为透明
contentPanel.setOpaque(false);
}
其中,我将“afternoon.jpg”这个图像文件设为背景, 背景为了高仿,截图是最快捷的方法,将qq界面截下来设为背景,包括之后的一些图像、图标、按钮都可以用。(qq截图快捷键ctrl+alt+a)
不过为了使效果看起来更逼真,我tencent的系统文件刨了一遍。
在qq2009以前,qq系统文件里可以直接翻出图像的源文件,不过后来随着qq的升级为了节省空间图像都被腾讯压缩在特定的RDB文件里了。
在这个系统目录下打开res.rdb(打开需要下载一个通用包文件处理工具) 将个人认为有用的那些文件夹解
压出来(自己挑选自己需要用到的,包括每天不同时间段的背景以及各种翻转图标),由于这些文件夹里的图片大部分格式是gft,动图是swf格式的,而java里能使用的只有png、jpg和gif,所以再下个GFT转换器,把所有gft格式的文件转换成png格式。
如果觉得翻系统文件麻烦还是直接截图就ok了,不过截图总会有误差的。
这是qq系统文件里的原图。
三、对某些方法的介绍
为了更好的安排组件,让某些组件按照个人的意愿以某种方式呈现出来就要调用某些方法。下边罗列一些我总结的有用的方法:
1.设置组件大小:
setSize()只能用于*的容器
setPreferredSize(Dimension preferredSize) 常用的设置各类组件、容器大小的方法,具体用法见代码
setBounds(int x, int y,int width,int height) 移动组件并调整其大小。由 x
和 y
指定左上角的新位置,由 width
和 height
指定新的大小。 和setPreferredSize比起来既可以设置大小也可以设置位置,而且容器组件均可。
2.设置透明
setOpaque(boolean isOpaque) 当括号内为false时,该组件透明
3.设置字体
setFont(Font font) 设置此组件的字体。
new Font(String name, int style, int size) 根据指定名称、样式和磅值大小,创建一个新 Font
。例如:setFont(new Font(“宋体”,0,15))
关于字体的方法都在Font类里,查api文档基本就可以明白
4.关于按钮的一些方法
setFocusPainted(boolean b)
设置 paintFocus
属性,对于要绘制的焦点状态,该属性必须为 true
。paintFocus
属性的默认值为 true
。一些外观没有绘制焦点状态;它们将忽略此属性。false即取消焦点框。
setContentAreaFilled(boolean b)
设置 contentAreaFilled
属性。如果该属性为 true
,则按钮将绘制内容区域。如果希望有一个透明的按钮,比如只是一个图标的按钮,那么应该将此属性设置为 false
。不要调用 setOpaque(false)
。contentAreaFilled
属性的默认值为 true
。
setBorderPainted(boolean b)
设置 borderPainted
属性。如果该属性为 true
并且按钮有边框,则绘制该边框。borderPainted
属性的默认值为 true
。
setIcon(Icon defaultIcon) 设置按钮的默认图标。如果没有显式地设置按下的图标,则此图标还被用作“按下”和“禁用”图标。
setRolloverIcon(Icon rolloverIcon) 设置按钮的翻转图标(当鼠标进入该组件时图标改变)。
setPressedIcon(Icon pressedIcon) 设置按钮的按下图标(当鼠标按下时该组件图标改变)。
-
三种状态下的多账号登录按钮
- 这几个方法取自AbstractButton类。该类定义了按钮和菜单项的一般行为。按钮可以进行配置,以及通过
Action
进行某种程度的控制。使用带有按钮的Action
具有除直接配置按钮之外的许多优点。详情查看api文档。 - 另外
setToolTipText(String text) 注册要在工具提示中显示的文本。光标处于该组件上时显示该文本。 关闭按钮和二维码登录按钮的工具提示
-
关于边框类的方法大多在BorderFactory里。
四、往各面板上添加组件
北边面板:
各面板的创建方式相同、、、
前边已经分析过了,北边面板需要在右上角添加三个不同功能的按钮
/**创建北边面板的方法**/
public JPanel creatPanelNorth(){
//实例化一个JPanel类的对象
JPanel PanelNorth = new JPanel();
PanelNorth.setLayout(null);
//设置北边面板容器的大小
PanelNorth.setPreferredSize(new Dimension(0,140));
//添加退出按钮
JButton jbn = new JButton(new ImageIcon("btn_close_normal.jpg"));
jbn.setBounds(342,-1,39,20);
jbn.setRolloverIcon(new ImageIcon("btn_close_highlight.png"));
jbn.setPressedIcon(new ImageIcon("btn_close_down.png"));
jbn.setBorderPainted(false);
jbn.setFocusPainted(false);
jbn.setToolTipText("关闭");
PanelNorth.add(jbn);
//添加最小化和设置按钮
JButton jb1 = new JButton(new ImageIcon("btn_mini_normal.jpg"));
jb1.setBounds(315,-1,28,20);
jb1.setRolloverIcon(new ImageIcon("btn_mini_highlight.png"));
jb1.setPressedIcon(new ImageIcon("btn_mini_down.png"));
jb1.setBorderPainted(false);
jb1.setFocusPainted(false);
jb1.setToolTipText("最小化");
PanelNorth.add(jb1);
JButton jb2 = new JButton(new ImageIcon("btn_set_normal.jpg"));
jb2.setBounds(288,-1,28,20);
jb2.setRolloverIcon(new ImageIcon("btn_set_hover.png"));
jb2.setPressedIcon(new ImageIcon("btn_set_press.png"));
jb2.setBorderPainted(false);
jb2.setFocusPainted(false);
jb2.setToolTipText("设置");
PanelNorth.add(jb2);
return PanelNorth;
}
北边面板的部分效果预览:
西边面板:
/**创建西边面板的方法**/
public JPanel creatPanelWest(){
//实例化一个JPanel类的对象
JPanel PanelWest = new JPanel();
//设置西边面板容器的大小
PanelWest.setPreferredSize(new Dimension(102,0));
//设置西边面板的布局方式为流式布局
PanelWest.setLayout(new FlowLayout(FlowLayout.RIGHT));
//实例化一个ImageIcon类的对象
ImageIcon imageWest = new ImageIcon("qq.jpg");
image2 = imageWest.getImage();
jpin = new JPanel(){
public void paint(Graphics g){
g.drawImage(image2, 0,0,null);
}
};
jpin.setPreferredSize(new Dimension(82,82));
jpin.setLayout(null);
jpin.setOpaque(false);
//将标签对象添加到面板上
//PanelWest.add(jlaWest);
//实例化一个JButton类的对象
jcoc = new JButton();
jcoc.setIcon(new ImageIcon("jcoc_normal.jpg"));
jcoc.setBounds(64, 64, 18, 18);
jcoc.setFocusPainted(false);
//jcoc.setBorderPainted(false);
//jcoc.setOpaque(false);
//jcoc.setContentAreaFilled(false);
jcoc.setRolloverIcon(new ImageIcon("jcoc_hover.jpg"));
//设置西边面板透明
PanelWest.setOpaque(false);
PanelWest.add(jpin);
jpin.add(jcoc);
//返回创建好的西边面板
return PanelWest;
}
因为西边面板上qq头像图标右下角还有有一个调出登录状态界面的按钮覆盖在该图标上,这个按钮到后期还要设置监听器,所以比较难办。经过冥思苦想,终于发现某大神的博客里用了重绘的方法。。。。(ps:当时还没学到重绘)
因为用到了重绘所以需要几个全局变量
在设置窗体可见之后取画布
在西边面板上完成重绘
中间面板:
/**创建中间面板的方法**/
public JPanel creatPanelCenter(){
//实例化一个JPanel类的对象
JPanel PanelCenter = new JPanel();
//设置中间面板的布局方式为流式布局
//FlowLayout flo = new FlowLayout(FlowLayout.LEFT,11,6);
PanelCenter.setLayout(null);
//实例化一个JcomboBox类的对象
String str []= {"123456787","123456788","123456789","","","","",""};
JComboBox jcoCenter = new JComboBox(str);
PanelCenter.add(jcoCenter);
jcoCenter.setBorder(null);
//设置下拉框可编辑
jcoCenter.setEditable(true);
//给下拉框添加数据
//jcoCenter.add(str);
jcoCenter.setBounds(7, 4, 185, 25);
jcoCenter.setFont(new Font("Calibri ",0,13));
//jcoCenter.setMaximumRowCount(100);
//实例化一个标签类的对象
JLabel jl1 = new JLabel("注册账号");
PanelCenter.add(jl1);
jl1.setFont(new Font("宋体",0,13));
jl1.setForeground(new Color(114,184,254));
jl1.setBounds(206,5,100,16);
ImageIcon image = new ImageIcon("buc.jpg");//实例化小键盘图标对象
JButton jbu = new JButton(image);
jbu.setPreferredSize(new Dimension(22,20));
jbu.setBorderPainted(false);
//实例化一个JPasswordField类的对象
JPasswordField jpaCenter = new JPasswordField();
jpaCenter.setLayout(new FlowLayout(FlowLayout.RIGHT,0,0));
//jpaCenter.setBorder(null);
LineBorder lin = new LineBorder(Color.WHITE,3,true);
jpaCenter.setBorder(lin);
jpaCenter.setBounds(7,38,185,23);
jpaCenter.add(jbu);
//设置大小
jpaCenter.setPreferredSize(new Dimension(185,25));
//添加到面板
PanelCenter.add(jpaCenter);
//实例化一个JLabel类的对象
JLabel jl2 = new JLabel("找回密码");
jl2.setFont(new Font("宋体",0,12));
jl2.setForeground(new Color(114,184,254));
jl2.setBounds(206, 40, 100, 16);
PanelCenter.add(jl2);
//实例化两个JCheckBox类的对象
JCheckBox jch1 = new JCheckBox("记住密码");
jch1.setFocusPainted(false); //选中时没有边框
jch1.setFont(new Font("宋体",0,13));//字体
jch1.setBounds(2, 70, 80, 15);
PanelCenter.add(jch1);
JCheckBox jch2 = new JCheckBox("自动登录");
jch2.setFocusPainted(false);
jch2.setFont(new Font("宋体",0,12));
jch2.setBounds(80, 70, 80, 15);
PanelCenter.add(jch2);
//设置复选框透明
jch1.setOpaque(false);
jch2.setOpaque(false);
//设置中间面板透明
PanelCenter.setOpaque(false);
return PanelCenter;
}
关于JComboBox
特别截图出来不过也不知该说什么,都是组件的实际应用,这一块儿的效果其实挺差的,仿真度不够,不过懒得弄了。
南边面板:
/**创建南边面板的方法**/
public JPanel creatPanelSouth(){
//实例化一个JPanel类的对象
JPanel PanelSouth = new JPanel();
//设置南边面板容器的大小
PanelSouth.setPreferredSize(new Dimension(0,51));
PanelSouth.setBorder(null);
//设置南边面板的布局方式为null
PanelSouth.setLayout(null);
//实例化三个JButton类的对象
//设置左边按钮
JButton jble = new JButton(new ImageIcon("corner_left.png"));
jble.setPreferredSize(new Dimension(40,40));
jble.setFocusPainted(false);
jble.setRolloverIcon(new ImageIcon("corner_left_hover.png"));
jble.setPressedIcon(new ImageIcon("corner_left_press.png"));
jble.setBorderPainted(false);
jble.setContentAreaFilled(false);
jble.setBounds(0,11,40,40);
JToolTip jtl = new JToolTip();
//jtl.setOpaque(false);
jtl.setBackground(Color.WHITE);
jble.setToolTipText("多账号登录");
//设置中间按钮
ImageIcon image = new ImageIcon("button_login_normal.png");
JButton jb = new JButton("登 录",image);
jb.setFont(new Font("宋体",0,13));
jb.setHorizontalTextPosition(SwingConstants.CENTER);//将文字放在图片中间
jb.setFocusPainted(false);//设置点击不出现边框
//设置透明
jb.setContentAreaFilled(false);
//设置翻转图标
jb.setRolloverIcon(new ImageIcon("button_login_hover.png"));
//设置选择图标
jb.setPressedIcon(new ImageIcon("button_login_down.png"));
//是否画边框
jb.setBorderPainted(false);
jb.setBounds(113,8,162,38);
//设置右边按钮
JButton jbri = new JButton(new ImageIcon("corner_right.png"));
jbri.setFocusPainted(false);
jbri.setRolloverIcon(new ImageIcon("corner_right_hover.png"));
jbri.setPressedIcon(new ImageIcon("corner_right_press.png"));
jbri.setBorderPainted(false);
jbri.setContentAreaFilled(false);
jbri.setBounds(336,9,38,38);
jbri.setToolTipText("二维码登录");
//设置下凹
//jb.setBorder(BorderFactory.createLoweredBevelBorder());
//将按钮对象添加到面板上
PanelSouth.add(jble);
PanelSouth.add(jb);
PanelSouth.add(jbri);
//返回创建好的南边面板
return PanelSouth;
}
都是调用方法貌似没什么好说的。。。。
五、各种监听器的添加
为了条理清晰,我把所有监听器添加都放在了这一项。
1.登录成功或失败
关于登录的监听器一定是全局变量,因为在*面板输入的账号密码而在南边面板点击的登录按钮。
所以该监听器要在*面板进行实例化
然后在创建南边面板的方法中,将该监听器绑定到登录按钮上
建立监听器类,该类包含事件的处理方法
public class LoginListener implements ActionListener {
private JComboBox jco ;//用来获取账号的对象
private JPasswordField jpa;//用来获取密码的对象
private JFrame jf;
/**
* 构造方法
*/
public LoginListener(JComboBox jco ,JPasswordField jpa,JFrame jf){
this.jco = jco;
this.jpa = jpa;
this.jf = jf;
}
/**
* 事件的处理方法
*/
public void actionPerformed(ActionEvent e) {
//System.out.println("你点击了"+e.getActionCommand()+"按钮");
//获取输入的账号,同时将账号转换为字符串
String name = (String)jco.getSelectedItem();
//获取输入的密码,同时将字符数组转换为字符串
String pwd = new String(jpa.getPassword());
//判断输入的账号和密码是否正确
if(name.equals("123456789") && pwd.equals("123456789")){
//关闭jf窗体
jf.dispose();
//实例化一个简单画板的界面
JFrame jfn = new JFrame();
jfn.setSize(289, 677);
jfn.setDefaultCloseOperation(3);
jfn.setLocation(800,0);
jfn.setLayout(null);
ImageIcon image = new ImageIcon("qqFrame.jpg");
JLabel jla = new JLabel( image);
jla.setBounds(0,0,image.getIconWidth(),image.getIconHeight());
//将标签添加到窗体的第二层面板上
jfn.getLayeredPane().add(jla,new Integer(Integer.MIN_VALUE));
//获取窗体的第一层板对象
JPanel contentPanel = (JPanel)jfn.getContentPane();
//设置第一层面板为透明
contentPanel.setOpaque(false);
//实例化一个退出按钮
JButton jbc = new JButton(new ImageIcon("close.jpg"));
jfn.add(jbc);
jbc.setBounds(250,0,39,20);
jbc.setBorderPainted(false);
jbc.setFocusPainted(false);
//监听退出按钮
Login_closeListener log = new Login_closeListener(jfn);
jbc.setActionCommand("Login_close");
jbc.addActionListener(log);
jfn.setUndecorated(true);
jfn.setVisible(true);
}else{//输入的账号和密码不正确
//弹出一个消息提示框对象
// JOptionPane.showMessageDialog(null, "你输入的账号和密码不匹配,请重新输入!");
jf.dispose();
JFrame jfn = new JFrame();
jfn.setSize(378, 293);//设置窗体的大小
jfn.setLocation(497, 242);
jfn.setUndecorated(true);
jfn.setResizable(true);//设置不能调整窗口大小
jfn.setVisible(true);
//实例化一个ImageIcon图标类的对象
ImageIcon image = new ImageIcon("false.jpg");
//实例化一个标签类的对象
JLabel back = new JLabel(image);
//设置标签显示的位置和大小
back.setBounds(0,0,image.getIconWidth(),image.getIconHeight());
//将标签添加到窗体的第二层面板上
jfn.getLayeredPane().add(back,new Integer(Integer.MIN_VALUE));
JPanel contentPanel = (JPanel)jfn.getContentPane();
//设置第一层面板为透明
contentPanel.setOpaque(false);
jfn.setLayout(null);
JButton jb = new JButton(new ImageIcon("btn_close_normal.jpg"));
jb.setBounds(340,0,39,20);
jb.setRolloverIcon(new ImageIcon("btn_close_highlight.png"));
jb.setPressedIcon(new ImageIcon("btn_close_down.png"));
jb.setBorderPainted(false);
jb.setFocusPainted(false);
jb.setToolTipText("关闭");
jfn.add(jb);
Login_closeListener ac = new Login_closeListener(jfn);
jb.addActionListener(ac);
}
}
}
输入成功的话会弹出如下界面
输入失败的话弹出如下界面:
这两个界面都是截图所以只实现了点x退出的功能。。。
2.退出界面的监听器
包括qq登录界面、登录成功的qq界面、登录失败界面都要实现点右上角x能退出的功能,所以要在每个退出按钮都是事件源要绑定监听器。然后再建一个类,该类实现接口。
public class Login_closeListener implements ActionListener {
private JButton jb;
private JFrame jf;
//重载构造方法
public Login_closeListener(JFrame jf){
this.jf = jf;
}
/**
* 事件处理方法
*/
public void actionPerformed(ActionEvent e){
jf.dispose();
}
}
在北边面板上实例化一个监听器,将这个监听器绑定在退出按钮上。
Login_closeListener lo = new Login_closeListener(jf);
jbn.addActionListener(lo);
3.最小化界面实现
ActionListener mini=new ActionListener(){
public void actionPerformed(ActionEvent e) {
jf.setExtendedState(jf.ICONIFIED); //最小化
}
};
jb1.addActionListener(mini);
在北边面板上建立一个匿名内部类,这个监听器能实现最小化功能,绑定到最小化按钮上。
4.小键盘和qq登录状态界面的实现
在西边面板上添加监听器,当点击西边面板上的按钮时,弹出qq登录状态界面
ActionListener li = new ActionListener(){
public void actionPerformed(ActionEvent e){
JFrame jfm = new JFrame();
jfm.setSize(106,143);
//jfm.setLocationRelativeTo(jcoc);
jfm.setUndecorated(true);
jfm.add(new JLabel(new ImageIcon("choose.jpg")));
jfm.setLocation(570,470);
jfm.setVisible(true);
LoginListener moleave = new LoginListener(jfm);
jfm.addMouseListener(moleave);
}
};
jcoc.addActionListener(li);
在中间面板上添加监听器,当点击小键盘按钮时,弹出小键盘界面
ActionListener li = new ActionListener(){
public void actionPerformed(ActionEvent e){
JFrame jfm = new JFrame();
jfm.setSize(370,111);
//jfm.setLocationRelativeTo(jcoc);
jfm.setUndecorated(true);
jfm.add(new JLabel(new ImageIcon("key.jpg")));
jfm.setLocation(600,445);
jfm.setVisible(true);
LoginListener moleave = new LoginListener(jfm);
jfm.addMouseListener(moleave);
}
};
jbu.addActionListener(li);
为了让弹出的界面能顺利关掉,我设置当鼠标进入界面时自动关闭界面
public class LoginListener extends MouseAdapter implements ActionListener {
public LoginListener(JFrame jf){
this.jf = jf;
}
public void mouseExited(MouseEvent e) {
jf.dispose();
}
}
这样做都只是看见截图,可以在小键盘上添加按钮并添加KeyListener达到输入效果。qq登录状态更改界面也可以用JComboBox变成下拉形式。
下一篇: 登录注册界面