图形用户接口
第一个GUI
import javax.swing.*;
public class SimpleGuil {
public static void main(String[] args) {
JFrame frame=new JFrame();
JButton button = new JButton("click me");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(button);
frame.setSize(300,300);
frame.setVisible(true);
}
}
- 取得按钮的ActionEvent
- 实现ActionListener这个接口
- 向按钮注册(告诉它你要监听事件)
- 定义事件处理的方法(实现接口上的方法)
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SimpleGui1B implements ActionListener {
JButton button;
public static void main(String[] args) {
SimpleGui1B gui = new SimpleGui1B();
gui.go();
}
public void go(){
JFrame frame=new JFrame();
button = new JButton("click me");
button.addActionListener(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(button);
frame.setSize(300,300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event){
button.setText("I have been clicked");
}
}
- 在GUI上面加东西的3种方法:
- 在frame上放置widget: 加上按钮,窗体,radio button等
- 在widget上绘制2D图形: 使用graphics对象来绘制图形
- 在widget上绘制JPEG图: 把图形画在widget上
- 调用Graphics2D的方法前,你必须把Graphics对象转换为Graphics2D
frame.getContentPane().add(BorderLayout.CENTER,button)
//指定位置 类型
- 位置有(north east south west center)
- 如果使用的是单一参数的add()方法会自动地把widget加到中心区域
- 内部类:一个类可以嵌套在另一个类的内部
- 内部类可以使用外部所有的方法与变量,就像是私用的也一样
- 内部类的实例一定会绑在外部类的实例上
class MyOuter{
private int x;
MyInner inner = new MyInner();
public void doStuff(){
inner.go();
}
class MyInner{
void go(){
x=42;
}
}
}
- 用内部类做动画
import javax.swing.*;
import java.awt.*;
public class SimpleAnimation {
int x=70;
int y=70;
public static void main(String[] args) {
SimpleAnimation gui =new SimpleAnimation();
gui.go();
}
public void go(){
JFrame frame =new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyDrawPanel drawPanel =new MyDrawPanel();
frame.getContentPane().add(drawPanel);
frame.setSize(300,300);
frame.setVisible(true);
for (int i=0;i<130;i++)
{
x++;
y++;
drawPanel.repaint();
try{
Thread.sleep(50);
}catch (Exception ex){
}
}
}
class MyDrawPanel extends JPanel{
public void paintComponent(Graphics g){
g.setColor(Color.white);
g.fillRect(0,0,this.getWidth(),this.getHeight());
g.setColor(Color.GREEN);
g.fillOval(x,y,40,40);
}
}
}
- 与音乐同步输出图形
import javax.sound.midi.*;
import javax.swing.*;
import java.awt.*;
public class MiniMusicPlayer3 {
static JFrame f=new JFrame("My First Music Video");
static MyDrawPanel ml;
public static void main(String[] args){
MiniMusicPlayer3 mini=new MiniMusicPlayer3();
mini.go();
}
public void setUpGui(){
ml=new MyDrawPanel();
f.setContentPane(ml);
f.setBounds(30,30,300,300);
f.setVisible(true);
}
public void go(){
setUpGui();
try{
Sequencer sequencer= MidiSystem.getSequencer();
sequencer.open();
sequencer.addControllerEventListener(ml,new int[] {127});
Sequence seq =new Sequence(Sequence.PPQ,4);
Track track =seq.createTrack();
int r=0;
for (int i=0;i<60;i+=4){
r=(int)((Math.random()*50)+1);
track.add(makeEvent(144,1,r,100,i));
track.add(makeEvent(176,1,127,0,i));
track.add(makeEvent(128,1,r,100,i+2));
}
sequencer.setSequence(seq);
sequencer.setTempoInBPM(120);
sequencer.start();
}catch (Exception ex){
ex.printStackTrace();
}
}
public MidiEvent makeEvent(int comd,int chan,int one,int two, int tick){
MidiEvent event=null;
try{
ShortMessage a=new ShortMessage();
a.setMessage(comd,chan,one,two);
event=new MidiEvent(a,tick);
}catch (Exception e){
}
return event;
}
class MyDrawPanel extends JPanel implements ControllerEventListener{
boolean msg =false;
public void controlChange(ShortMessage event){
msg=true;
repaint();
}
public void paintComponent(Graphics g){
if (msg){
Graphics2D g2=(Graphics2D) g;
int r =(int) (Math.random()*250);
int gr=(int) (Math.random()*250);
int b=(int) (Math.random()*250);
g.setColor(new Color(r,gr,b));
int ht=(int) ((Math.random()*120)+10);
int width=(int) ((Math.random()*120)+10);
int x=(int) ((Math.random()*40)+10);
int y=(int) ((Math.random()*40)+10);
g.fillRect(x,y,ht,width);
msg=false;
}
}
}
}
Swing
-
组件是可以嵌套的,从技术上来说widget是个Swing的组件,几乎所有的GUI组件都来自于java.swing.JComponent
-
创建GUI四个步骤
- 创建window(JFrame)
- 创建组件
- 把组件加到frame上
- 显示出来
-
布局管理器用来控制所关联组件上携带的其他组件,每个背景组件都可以有自定义规则的布局管理器
-
不同的布局管理器有不同的策略
BorderLayout(框架) 把背景组件分割成5个区域,每个区域只能放一个组件,组件通常不会取得默认大小 FlowLayout(面板) 每个组件都会依照理想的大小呈现,并且会从左到右依照加入的顺序以可能会换行的方式排列 BoxLayout 每个组件使用默认的大小,按照加入顺序排列,以垂直的方向来排列,不会自动换行 -
在BorderLayout中,中间区域只能捡剩下区域的大小
-
pack()方法会使window的大小符合内含组件的大小
-
可以调用setLayout()来改变面板的布局管理器
-
JTextArea范例
package demo11;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TextAreal implements ActionListener {
JTextArea text;
public static void main(String[] args) {
TextAreal gui=new TextAreal();
gui.go();
}
public void go(){
JFrame frame=new JFrame();
JPanel panel=new JPanel();
JButton button=new JButton("Just Click It");
button.addActionListener(this);
text=new JTextArea(10,20);
text.setLineWrap(true);
JScrollPane scroller=new JScrollPane(text);
scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
panel.add(scroller);
frame.getContentPane().add(BorderLayout.CENTER,panel);
frame.getContentPane().add(BorderLayout.SOUTH,button);
frame.setSize(350,300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent ev){
text.append("button clicked \n");
}
}
- JList的构造函数需要一个任意类型的数组。不一定要是String,但会用String来表示项目