JAVA学习——初学GUI

首先了解一下java中有哪些可以用来实现用户交互的

1. 窗口

Java提供的JFrame类的实例就是一个底层容器,即通常所讲的窗口
JFrame()创建一个无标题的窗口,它的构造函数有

在这里插入图片描述
当需要一个窗口时,可使用JFrame或其子类创建一个对象。
需要注意的是,窗口默认被系统添加到显示器屏幕上,因此不允许将一个窗口添加到另一个容器中。

举一个例子

import javax.swing.*;
import java.awt.*;

class myJFrame extends JFrame
{
    myJFrame(String s)
    {
        super(s);
        setBounds(100,100,320,240);
        setResizable(true);
        setVisible(true);
        //setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

}
public class test_JFrame {
    public static void main(String args[])
    {
        myJFrame frm1 = new myJFrame("第一个窗口");
        //frm1.setBackground(Color.blue);
        myJFrame frm2 = new myJFrame("第二个窗口");
        //frm2.setBackground(Color.BLACK);
        Container con1 = frm1.getContentPane();
        con1.setBackground(Color.BLUE);

        Container con2 = frm2.getContentPane();
        con2.setBackground(Color.CYAN);

        frm1.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //释放当前窗口
        frm2.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    }
}

我在这里利用了JFrame写了一个自己的窗口类。
然后在主类里面创建了两个myJFrame的对象frm1与frm2
接下来比较重要的是设置这两个窗口的背景颜色
首先我们可以看到我先利用的frm1和frm2自己的setBackground()方法,结果发现是这样的:
在这里插入图片描述
窗口的背景颜色并没有改变,但这是为什么呢?
从这篇文章中我们可以找到答案
查阅了一下博客我们发现,原来我们设置的JFrame的背景色会被JFrame的面板给盖住,那么不如直接设置面板的颜色。通过这篇文章我们可知,JFrame的内容面板可以通过.getContentPane()方法给提取出来,所以我们可以通过新建一个Container对象con1来提取出frm1的内容面板,然后调用setBackground()方法进行设置背景颜色,比如

Container con1 = frm1.getContentPane();
        con1.setBackground(Color.BLUE);

也可以通过直接调取的方法改变窗口的背景色,比如

frm1.getContentPane().setBackground(Color.BLUE);

结果发现这两种方法的实现都是可行的。

再讲下public void setDefaultCloseOperation(int operation),该方法用来设置单击窗体右上角的“关闭图标”后,程序会作出怎样的处理。其中形参operation取JFrame类中的下列int型static常量,程序根据参数operation取值做出不同的处理:

  • DO_NOTHING_ON_CLOSE(什么都不做)
  • HIDE_ON_CLOSE(隐藏当前窗口)
  • DISPOSE_ON_CLOSE(隐藏当前窗口,并释放窗体占有的其他资源)
  • EXIT_ON_CLOSE(结束窗口所在的应用程序)

其次是pubilc void setExtendedState(int state),这是设置窗口的扩展状态,其中参数state取JFrame类中的下列类常量:

  • MAXIMIZED_HORIZ(水平方向最大化)
  • MAXIMIZED_VERT(竖直方向最大化)
  • MAXIMIZED_BOTH(水平,垂直方向都最大化)

菜单

菜单条/菜单/菜单项作是窗口常用的组件,菜单放在菜单条里,菜单项放在菜单里。
举个例子:
在这里插入图片描述

这是一个带有菜单的窗口
“菜单”右边的
的这个图形就是菜单条,也就是菜单放置的位置
JComponent类的子类JMenubar负责创建菜单条。
JFrame类里有一个将菜单条放置到窗口中的方法:
setJMenuBar(JMenuBar bar);

然后


在这里插入图片描述
就是“菜单”,JComponent类的子类JMenu负责创建菜单。

再接着就是“菜单项”
也就是
在这里插入图片描述

在这里插入图片描述
菜单项可以用JComponent类的子类JMenuItem创建。
**需要注意的是JMenu是JMenuItem的子类,也就是说“菜单”也是“菜单项”的一种

然后我们举个例子:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import static javax.swing.JFrame.*;

class ButtonEvent implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        String str = e.getActionCommand();
        System.out.println(str+":"+str.length());
    }
}
class WindowMenu extends JFrame{
    //创建菜单条
    JMenuBar menubar;
    //创建菜单
    JMenu menu,subMenu;
    //创建菜单项
    JMenuItem item1,item2;

    ButtonEvent listener = new ButtonEvent();

    public WindowMenu() {}

    public WindowMenu(String s,int x,int y, int w,int h) {
        init(s);
        setLocation(x,y);
        setSize(w,h);
        setVisible(true);
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    }

    void init(String s)
    {
        setTitle(s);
        menubar = new JMenuBar();
        menu = new JMenu("菜单");
        subMenu = new JMenu("软件项目");
        //为使菜单项有一个图标,可以用图标类Icon声明一个图标,然后使用其子类ImageIcon类创建一个图标
        item1 = new JMenuItem("Java话题",new ImageIcon("a.gif"));
        item2 = new JMenuItem("动画话题",new ImageIcon("b.gif"));
        //setAccelerator()的作用:
        //设置组合键,它能直接调用菜单项的操作侦听器而不必显示菜单的层次结构。
        //所以用这个方法就能制作我们所要的快捷键了。
        item1.addActionListener(listener);
        item1.setAccelerator(KeyStroke.getKeyStroke('A'));//这里的意思就是‘A’作为打开item1的快捷键
        item2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_DOWN_MASK));
        //而item2需要CTRL+S键才能打开

        menu.add(item1);
        //在菜单末尾附加一个新的分隔符。
        menu.addSeparator();

        menu.add(item2);
        menu.add(subMenu);
        subMenu.add(new JMenuItem("汽车销售系统",new ImageIcon("c.gif")));
        subMenu.add(new JMenuItem("农场信息系统",new ImageIcon("d.gif")));
        menubar.add(menu);
        setJMenuBar(menubar);
    }
}
public class test_Menu {
    public static void main(String args[])
    {
        WindowMenu win = new WindowMenu("带菜单的窗口",20,30,200,190);

    }
}

在这里因为我们没给item1的点击实现”监听器注册“,所以为了达到成果,我们加入了一个ButtonEvent的类的监视器,让其呈现出快捷键的实现与鼠标单击的实现。
而快捷键

 item1.setAccelerator(KeyStroke.getKeyStroke('A'));
 item2.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,InputEvent.CTRL_DOWN_MASK));

则是由这两条语句实现的,具体的操作可在后续的”键盘事件中查找“。

下面我们看一下快捷键的实现与鼠标的实现:
在这里插入图片描述
我们发现结果是完全一致的,所以可以表明:快捷键的设置是成功的。
但是注意一点,因为快捷键的设置为’A’,所以只有大写字母A才能触发快捷键的操作。

2.事件

在学习处理事件时,必须很好地掌握事件源、监视器、处理事件的接口这三个概念。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这是基本的概念,然后对于监听器而言,需要一个对象对“事件源”进行监视,以便对发生的事件做出处理。事件源通过调用相应的方法将某个对象***注册***为自己的监听器,例如

事件源.addActionListener(监视器);

对于注册了监视器的文本框,在文本框获得输入焦点后,如果用户按回车键,Java运行环境就自动用ActionEvent类创建了一个对象,也就是发生了ActionEvent事件。也就是说,事件源注册监听器后,相应的操作就会导致相应的事件的发生,并通知监视器,监听器就会做出相应的处理。

在这里插入图片描述
对于一系列的操作而言,我个人的理解是:
①首先先确立“事件源”
②然后给事件源注册一个监听器,也就是

事件源.addActionListener(监视器);

③在外面实现自己的监视器,通过implements实现监听器接口,将其抽象方法具体化,最后在需要的方法内完成想要得到的操作即可。

举个ActionEvent的例子:

import javax.swing.plaf.basic.BasicOptionPaneUI;
import java.awt.*;
import java.awt.event.*;

class myButtonFrame extends Frame
{
    Button btn;

    myButtonFrame(String s)
    {
        super(s);

        setSize(400,300);

        btn = new Button("Click");

        add(btn);

        //创建事件监听器
        ButtonListener bl = new ButtonListener();
        ButtonListener2 bl2 = new ButtonListener2();

        //创建事件监听器注册
        btn.addActionListener(bl);
        btn.addActionListener(bl2);

        //显示窗体
        setVisible(true);
    }

    //事件监听器1
    private  class ButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("click-respond_1");
        }
    }

    //事件监听器2
   private class ButtonListener2 implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("click-respond_2");
            System.exit(1);
        }
    }
}
public class test_ActionEvent {
    public static void main(String args[])
    {
        myButtonFrame frm = new myButtonFrame("ActionEventTest");
    }
}

注意这里的一个细节:

        //创建事件监听器注册
        btn.addActionListener(bl);
        btn.addActionListener(bl2);

在这里我在一个按钮上面添加了两个监听器,也可以理解为,现在有A和B两个***独立的***壮汉在监视着C这个囚徒,一旦C这个囚徒发生了任何动作,A和B都会做出相应的动作。
所以说,A和B的动作都是独立的,也是会一起发生的(但是由于bl的操作写在之前,所以会率先发生)。
然后是关于监视器的实现

 //事件监听器1
    private  class ButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("click-respond_1");
        }
    }

    //事件监听器2
   private class ButtonListener2 implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            System.out.println("click-respond_2");
            System.exit(1);
        }
    }

这是对于不同的监视器的实现,我们可以看到基本写法都是

class ButtonListener implements ActionListener {
    public void actionPerformed(              ) {
	  /*  按钮事件所进行的具体工作  */
	}
}

3.绘制基本图形

Component类中有一个方法public void paint(Graphics g),程序可以在其子类中重写这个方法,当程序运行时,Java运行环境会用Graphics2D将参数g实例化,对象g就可以在重写paint方法的组件上绘制图形、图像等。

基本的绘制操作为
在一个自定义继承JPanel的类里重写paint方法:

public void paint(Graphics g)
{
  Graphics2D g_2d = (Graphics2D) g;
  g_2d.setColor(Color.xxx);
  //实例化
  基本图形 a = new 基本图形类的构造函数;
  g_2d.draw(a); //是指描边
  g_2d.fill(a); //是指填充
}

但由于有时无法实现重写类,也就是说重写paint()的形参Graphics g无法获取,所以可以进行以下操作

Graphics g = getGraphics()

来获取画布,具体操作如下。

public void paint()
{
  Graphics g = getGraphics()
  Graphics2D g_2d = (Graphics2D) g;
  g_2d.setColor(Color.xxx);
  //实例化
  基本图形 a = new 基本图形类的构造函数;
  g_2d.draw(a); //是指描边
  g_2d.fill(a); //是指填充
}

然后在getGraphics()里面有一个函数
在这里插入图片描述
通过使用当前绘图表面的背景色进行填充来清除指定的矩形。

但是在实现绘画的时候一定一定要记住,要把画布添加到窗口中。

因为如果没有添加到窗口中,事件虽然会触发,但是在我们人为看来是没有响应的。

4.鼠标事件

再写一个关于MouseEvent的触发事件

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

//这里是事件和监听器注册
class WindowMouse extends JFrame
{
    JTextField text;
    JButton button;
    //设置一个多行文本框
    JTextArea textArea;
    //设置监听器
    MousePolice police;
    WindowMouse(){
        init();
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    void init()
    {
        setLayout(new FlowLayout());
        text = new JTextField(8);
        textArea = new JTextArea(5,28);
        police = new MousePolice();
        police.setJTextArea(textArea);
        button = new JButton("按钮");

        //监听器注册
        button.addMouseListener(police);
        addMouseListener(police);

        add(button);
        add(text);
        //JScrollPane()是创建一个滚动窗格
        add(new JScrollPane(textArea));
    }
}

//这里是监听器
class MousePolice implements MouseListener
{
    JTextArea area;
    public void setJTextArea(JTextArea area)
    {
        this.area = area;
    }

    public void mousePressed(MouseEvent e)
    {
        area.append("\n鼠标按下,位置:" + "(" +e.getX() + "," + e.getY() + ")");
    }

    public void mouseReleased(MouseEvent e)
    {
        area.append("\n鼠标释放,位置:"+"("+e.getX()+","+e.getX()+")");
    }

    public void mouseEntered(MouseEvent e)
    {
        //.getSource()返回的是个对象
        if(e.getSource() instanceof JButton)
        {
            area.append("\n鼠标进入按钮,位置:"+"("+e.getX()+","+e.getX()+")");
        }
        if(e.getSource() instanceof  JTextField)
        {
            area.append("\n鼠标进入文本框,位置:"+"("+e.getX()+","+e.getX()+")");
        }
        if(e.getSource() instanceof JFrame)
        {
            area.append("\n鼠标进入窗口,位置:"+"("+e.getX()+","+e.getX()+")");
        }
    }
    public void mouseExited(MouseEvent e)
    {
        area.append("\n鼠标退出,位置:"+"("+e.getX()+","+e.getX()+")");
    }
    public void mouseClicked(MouseEvent e)
    {
        if(e.getClickCount() >= 2)
        area.append("\n鼠标连击,位置:"+"("+e.getX()+","+e.getX()+")");
    }
}

public class test_MouseEvent {
    public static void main(String args[])
    {
        WindowMouse win = new WindowMouse();
        win.setTitle("处理鼠标事件");
        win.setBounds(10,10,460,360);
    }
}

这个事件主要为:显示鼠标在执行操作x时所在的位置。
个人认为重要的代码块为:

void init()
    {
       police.setJTextArea(textArea);
       /
       button.addMouseListener(police);
       addMouseListener(police);
       
    }

这里是实行了监听器注册

class MousePolice implements MouseListener
{
    JTextArea area;
    public void setJTextArea(JTextArea area)
    {
        this.area = area;
    }

    public void mousePressed(MouseEvent e)
    {
        area.append("\n鼠标按下,位置:" + "(" +e.getX() + "," + e.getY() + ")");
    }

    public void mouseReleased(MouseEvent e)
    {
        area.append("\n鼠标释放,位置:"+"("+e.getX()+","+e.getX()+")");
    }

    public void mouseEntered(MouseEvent e)
    {
        //.getSource()返回的是个对象
        if(e.getSource() instanceof JButton)
        {
            area.append("\n鼠标进入按钮,位置:"+"("+e.getX()+","+e.getX()+")");
        }
        if(e.getSource() instanceof  JTextField)
        {
            area.append("\n鼠标进入文本框,位置:"+"("+e.getX()+","+e.getX()+")");
        }
        if(e.getSource() instanceof JFrame)
        {
            area.append("\n鼠标进入窗口,位置:"+"("+e.getX()+","+e.getX()+")");
        }
    }
    public void mouseExited(MouseEvent e)
    {
        area.append("\n鼠标退出,位置:"+"("+e.getX()+","+e.getX()+")");
    }
    public void mouseClicked(MouseEvent e)
    {
        if(e.getClickCount() >= 2)
        area.append("\n鼠标连击,位置:"+"("+e.getX()+","+e.getX()+")");
    }
}

其实这一部分也可以设置为WindowMouse的内部类,稍微需要的改动则为:删去成员变量JTextArea area; 删去成员函数public void setJTextArea(JTextArea area);
然后把抽象的方法中的对象area改为textArea即可。、

注意一点,MouseEvent类中有下列几个重要的方法:
getX():获取鼠标指针在事件源坐标系中的x坐标。
getY():获取鼠标指针在事件源坐标系中的y坐标。
getButton():获取鼠标的左键或右键。鼠标左键和右键分别用.Button1和.Button2来表示。
getClickCount():获取鼠标点击次数。
getSource():获取发生鼠标事件的事件源。(可在此次的 public void mouseEntered(MouseEvent e) 方法中找到。)


版权声明:本文为weixin_45693164原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。