第3回
複雑なレイアウトのイベント処理、画像
データの読込み、テーブルの使用
キーポイント
•
レイアウトについて
– 前回までのレイアウト
– レイアウトの補足機能
– 固定座標を用いたレイアウト
– Grid Layout
•
CardLayoutについて
– Card Layout
– Card Layoutによる複数ページ表示
•
ファイルの読み込み
– JFileChooserクラス
– java.awt.FileDialog
– 画像データの読み込みと表示
•
テーブルの利用
– JTableクラス
– テーブルデータの初期設定
– Vector型データの使用
前回までに学んだGUIのレイアウト
•
BorderLayout、FlowLayoutなどの標準的なレイアウトを学んだ
•
今回は、更に複雑なデザインのGUIを作るためのレイアウト、またそれに伴うイベ
ント処理について学習していく
2
BorderLayout
FlowLayout
基本的なレイアウトの補足
•
フレームのサイズを固定する
– setResizable()メソッドを用いて、引数にfalseを与えることでフレームのサイズを固定する
public class Practice03 extends JFrame implements ActionListener {
JPanel jp1;
public static void main(String[] args){
new Practice03("Teaching3 Test Layout");
}
Practice03(String title){
jp1 = new JPanel();
jp1.add(new JLabel(
"This is a JPanel with default layout in page 1"));
jp1.add(new JButton("I'm a button"));
jp1.add(new JLabel("I'm a label"));
add(jp1);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 300);
setResizable(false);
setTitle(title);
setVisible(true);
}
setResizable(falese)で
サイズが固定される
基本的なレイアウトの補足(2)
•
BorderLayoutの記述の仕方
– BorderLayoutの位置指定には絶対指定と相対指定がある。どちらを使っても良いが、混在できない
4
JPanel jp1,jp2;
Practice03(String title){
… …
jp2 = new JPanel(new BorderLayout());
jp2.add(new JLabel(“
This is a JPanel with BorderLayout in page 2"), "Center");
jp2.add(new JButton("North"), "North");
jp2.add(new JButton("South"), "South");
jp2.add(new JButton("West"), "West");
jp2.add(new JButton("East"), "East");
//以下のように記述することもできる
//jp2.add(new JButton("North"), BorderLayout.PAGE_START);
//jp2.add(new JButton("South"), BorderLayout.PAGE_END);
//jp2.add(new JButton("West"), BorderLayout.LINE_START);
//jp2.add(new JButton("East"), BorderLayout.LINE_END);
add(jp2);
//add(jp1);
… …
}
絶対指定 相対指定 位置 BorderLayout.CENTER BorderLayout.CENTER 中央 BorderLayout.NORTH BorderLayout.PAGE_START 上 BorderLayout.SOUTH BorderLayout.PAGE_END 下 BorderLayout.WEST BorderLayout.LINE_START 左 BorderLayout.EAST BorderLayout.LINE_END 右レイアウトマネージャを用いないレイアウト
•
レイアウトマネージャを無効にする
– レイアウトマネージャを無効にした場合は、固定座標によってコンポーネントを配置する
– Javaアプリケーションは色々な環境で実行される可能性があるため、基本的にはレイアウトマネー
ジャの使用が推奨されるが、座標指定でアプリケーションを作成した場合などは固定座標を用いる
JPanel jp1,jp2,jp3; Practice03(String title){ … … jp3 = new JPanel(); jp3.setLayout(null);JLabel jlabel = new JLabel(
"This is a JPanel without layout in page 3");
jlabel.setBounds(10, 10, 300, 20);
jp3.add(jlabel);
JButton jbutton1 = new JButton("I'm a button");
jbutton1.setBounds(10, 35, 150, 20);
jp3.add(jbutton1); JButton jbutton2 =
new JButton("I'm another button");
jbutton2.setBounds(10, 60, 200, 20); jp3.add(jbutton2); add(jp3); //add(jp2); … … (10,10,300,20) (10,110,200,20) (10,60,150,20) 150 200 60 110
座標 サイズ
GridLayoutの作成
•
GridLayoutクラスを用いて画面を作成する
– GridLayoutは対象となる領域全体を指定した行数と列数に分割する
– 配置されたコンポーネントは全て同じサイズに調節される
6
import java.awt.GridLayout;
… …
… …
JPanel jp1,jp2,jp3,jp4;
Practice03(String title){
… …
//行と列数を指定
(行,列) -> (2x2)
//指定がない場合はコンポーネントが横に配置される
jp4 = new JPanel(new GridLayout(2, 2));
jp4.add(new JButton("This is"));
jp4.add(new JButton("a JPanel with"));
jp4.add(new JButton("2*2 GridLayout"));
jp4.add(new JButton("in page 4"));
add(jp4);
//add(jp3);
… …
}
行2
列2
CardLayoutについて
•
CardLayoutクラスは複数コンポーネントを切り替えて表示できるレイアウトマネー
ジャー
•
それぞれのカードにコンポーネントを登録した複数のカードを内部的に保持し、表
示するカードを切り替えることで表示するコンポーネントを切り替える
•
CardLayoutクラスの持つメソッドは以下の通り
first()
- コンテナの最初のカードに切り替える
last()
- コンテナの最後のカードに切り替える
next()
- 指定されたコンテナの次のカードに切り替える
previous()
-指定されたコンテナの前のカードに切り替える
next()
next()
next()
previous()
previous()
previous()
CardLayoutについて(2)
•
レイアウトの動作の確認のために簡単なサンプルプログラムを作る
8
import javax.swing.*;
import java.awt.CardLayout;
import java.awt.event.*;
public class CardLayoutTest
extends JFrame implements ActionListener{
JPanel jpMain;
CardLayout cl;
public static void main(String[] args){
CardLayoutTest frame = new CardLayoutTest2();
}
CardLayoutTest(){
// Card1
JPanel c1 = new JPanel();
c1.add(new JLabel("card1"));
c1.add(new JButton("button"));
// Card2
JPanel c2 = new JPanel();
c2.add(new JLabel("card2"));
c2.add(new JTextField("", 10));
// Card3
JPanel c3 = new JPanel();
c3.add(new JLabel("card3"));
c3.add(new JCheckBox("checkbox1"));
c3.add(new JCheckBox("checkbox2"));
jpMain = new JPanel();
cl= new CardLayout();
//パネルにCardLayoutを設定する
jpMain.setLayout(cl);
//作成したカードをパネルに設定する
//この時点ではcard1のみ表示される
jpMain.add(c1, "card1");
jpMain.add(c2, "card2");
jpMain.add(c3, "card3");
add(jpMain,BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
setSize(300,200);
setTitle("CardLayoutTest");
setVisible(true);
}
CardLayoutについて(3)
•
カード移動用のボタンとイベントの追加を行う
… … CardLayoutTest(){ … … // カード移動用ボタンJButton firstbtn = new JButton("First"); firstbtn.addActionListener(this);
firstbtn.setActionCommand("First"); JButton prevbtn = new JButton("Prev"); prevbtn.addActionListener(this);
prevbtn.setActionCommand("Prev"); JButton nextbtn = new JButton("Next"); nextbtn.addActionListener(this);
nextbtn.setActionCommand("Next"); JButton lastbtn = new JButton("Last"); lastbtn.addActionListener(this);
lastbtn.setActionCommand("Last"); JPanel btnp = new JPanel(); btnp.add(firstbtn); btnp.add(prevbtn); btnp.add(nextbtn); btnp.add(lastbtn); add(btnp, BorderLayout.SOUTH);
(イベント処理)
public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); if (cmd.equals("First")) { cl.first(jp); } else if (cmd.equals("Last")) { cl.last(jp); } else if (cmd.equals("Next")) { cl.next(jp); } else if (cmd.equals("Prev")) { cl.previous(jp); } }
プログラムを実行して動作を確認して下さい
CardLayoutについて(4)
•
先ほど作ったレイアウトを用いて画面を作成する
10
public class CardLayoutTest 2extends JFrameimplements ActionListener { JPanel jpMain;
CardLayout cl;
JPanel[] jps;
JButton jb;
public static void main(String[] args) {
new CardLayoutTest 2(" CardLayoutTest 2"); }
public CardLayoutTest2(String title){ cl = new CardLayout();
jpMain = new JPanel();
jpMain.setLayout(cl); add(jpMain, "Center"); // 各ページ用のパネルを配列に置きなおす jps = new JPanel[4]; // 今回のレイアウトの演習jp1~jp4で作成したパネルを // そのまま使用して下さい jps[0] = new JPanel();
jps[0].add(new JLabel("This is a JPanel with default layout in page 1"));
jps[0].add(new JButton("I'm a button")); jps[0].add(new JLabel("I'm a label"));
// メインのパネルにaddする際に、カードの名前をつける jpMain.add(jps[0], "page1"); … … // 同じようにjp2~jp4の部分も作成 // 画面下部のボタンはCardLayoutTest()で作成した // ボタン用のJPanelを使用 … …
JPanel btnp = new JPanel(); btnp.add(firstbtn); … … add(btnp, BorderLayout.SOUTH); setTitle(title); setSize(400,300); setLocation(400,300); setResizable(false); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } // (イベント処理)
public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand();
// イベント処理部もCardLayoutTest()で作成した // ボタン用のイベント処理を記述
CardLayoutについて(5)
•
実行して画面の動作を確認
First
jps[0]
jps[1]
jps[2]
jps[3]
next
Prev
ファイルの読み込み(1)
•
JFileChooserクラスを用いたファイルの読み込み
– 画面上でファイル名を選択できるダイアログを表示する場合に利用する
12
public class JFileChooserTest extends JFrameimplements ActionListener { JLabel label;
public static void main(String[] args) { JFileChooserTest frame = new
JFileChooserTest("JFileChooserTest"); }
JFileChooserTest(String title) {
JButton button = new JButton("Select File"); button.addActionListener(this);
JPanel btnPanel = new JPanel(); btnPanel.add(button);
label = new JLabel();
JPanel lbPanel = new JPanel(); lbPanel.add(label); add(lbPanel, BorderLayout.CENTER); add(btnPanel, BorderLayout.PAGE_END); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(300, 200); setTitle(title); setVisible(true); }
public void actionPerformed(ActionEvent e) {
JFileChooser filechooser = new JFileChooser();
int selected = filechooser.showOpenDialog(this); if (selected == JFileChooser.APPROVE_OPTION) {
File file = filechooser.getSelectedFile(); label.setText(file.getName()); } } }
ダイアログを開くボタンをクリックし、
動作を確認して下さい
ファイルを選択し、画面内のラベ
ルに選択した情報が適用されるの
を確認して下さい
ファイルの読み込み(2)
•
JFileChooserクラスを用いたファイルの読み込み
– 画面上でファイル名を選択できるダイアログを表示する場合に利用する
public void actionPerformed(ActionEvent e) { JFileChooser filechooser = new JFileChooser(); // ダイアログを開く
// 引数に指定した文字列をボタンに使用できる -> “実行” int selected = filechooser.showOpenDialog(this,”実行”); // 選択された操作に対応するイベントを選択する
if (selected == JFileChooser.APPROVE_OPTION){
File file = filechooser.getSelectedFile(); label.setText(file.getName());
} else if (selected ==JFileChooser.CANCEL_OPTION){ label.setText("キャンセルされました");
} else if (selected ==JFileChooser.ERROR_OPTION){ label.setText("エラー又は取消しがありました"); } }
定義値
値
ボタンの種類
JFileChooser.APPROV E_OPTION0
引数で指定した文字列が表示されたボタ
ンが選択された場合
JFileChooser.CANCEL _OPTION1
「取消し」ボタンが選択された場合
ファイルの読み込み(3)
•
java.awt.FileDialogを使ってファイルの読み込みをする
14
// 画面のデザインは先ほどのプログラムを利用して下さい… …
public void actionPerformed(ActionEvent e) { // FileDialogを開く
// 第一引数:ターゲットとなるフレーム // 第二引数:ダイアログのタイトル // (第三引数:ダイアログのモード)
FileDialog fd = new FileDialog(this, "File Select");
// FileDialogを表示する
fd.setVisible(true);
// getDirectory() : 選択したファイルのパスを取得 // getFile() : 選択したファイルの名前を取得
String fullpath = fd.getDirectory() + fd.getFile();
label.setText(fullpath); }
適当なファイルを選択して、画面
の表示を確認して下さい
ファイルの読み込み(4)
•
java.awt.Canvasを継承したMyCanvasクラスを用いて画像の表示をする
public class PictureViewer extends JFrame implements ActionListener { JPanel jp; MyCanvas mc; String fpath,fname; JButton JBselect; FileDialog fd_load; … … //mainメソッド省略
public PictureViewer(String title) { setTitle(title);
jp = new JPanel();
JBselect = new JButton("Select a picture"); JBselect.addActionListener(this); jp.add(JBselect); // 画像表示用にMyCanvasオブジェクトを作成 mc = new MyCanvas(); add(jp, "North"); add(mc, "Center"); setSize(360, 360); setLocation(400, 200); // ウィンドウが閉じられた時の処理 addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e) {
System.exit(0); }
});
setVisible(true);
fd_load = new FileDialog(this, "Open file",
public void actionPerformed(ActionEvent arg0) { fd_load.setVisible(true);
fpath = fd_load.getDirectory(); fname = fd_load.getFile();
if((fpath != null) && (fname != null)) {
// display()メソッドに指定したファイルのパスを持った // Fileオブジェクトを渡す
this.display(new File(fpath + fname)); }
}
public void display(File f) { try{ // 読み込んだファイルの画像データをセット BufferedImage bi = ImageIO.read(f); mc.setImage(bi); this.setTitle("PictureViewer - [" + f.getName() + "]"); } catch (Exception e) { e.printStackTrace(); } mc.repaint(); } }
MyCanvasクラス
MyCanvas.java
ファイルの読み込み(5)
•
java.awt.Canvasを継承したMyCanvasクラスを用いて画像の表示をする
16
適当な画像ファイルを選択して動作を確認して下さい
(余裕のある人は、MyCanvasクラスの内部の動作を
確認してみて下さい)
テーブルの利用
•
JTableクラスを利用して、デザインにテーブルを利用する
– JTableクラスは表形式の形でデータを表示する際に使用する
– データベースのデータのように扱うために、同じ列のデータはデータ形式を統一する必要がある
public class TableViewer extends JFrame {// テーブルデータ String[][] tdata = { {"りんご","150","7500","50"}, {"みかん","50","4000","20"}, {"ぶどう","200","8000","60"}, {"バナナ","250","15000","40"} }; // テーブルの要素名 String[] columnNames = {"商品", "価格(円)", "売上(円)", "在庫(個)"}; public static void main(String[] args){
new TableViewer(" Teaching 5 Table Viewer "); }
public TableViewer(String title){ JPanel p = new JPanel(); // テーブルの作成
JTable table = new JTable(tdata, columnNames); // サイズの自動設定
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); // JScrollPaneオブジェクト上にテーブルを配置
JScrollPane sp = new JScrollPane(table); sp.setPreferredSize(new Dimension(300, 100)); p.add(sp);
JTable table2 = new JTable(4,4);
table2.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); JScrollPane sp2 = new JScrollPane(table2);
sp2.setPreferredSize(new Dimension(300, 100)); p.add(sp2); add(p, BorderLayout.CENTER); setTitle(title); setSize(400,250); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } }
テーブルの利用(2)
•
初期データの設定
– テーブルのデータからJTableオブジェクトを作成すると、データを後から追加することができない
– DefaultTableModelクラスのオブジェクトを用いることで、それが可能となる
18
import javax.swing.table.DefaultTableModel; … …public TableViewer(String title){ JPanel p = new JPanel();
// 引数には、テーブルのデータを与える
DefaultTableModel tm = new
DefaultTableModel(tdata,columnNames);
// DefaultTableModelのオブジェクトを引数として与える
JTable table = new JTable(tm);
//JTable table = new JTable(tdata, columnNames); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); JScrollPane sp = new JScrollPane(table);
sp.setPreferredSize(new Dimension(300, 100)); p.add(sp); … … } }
表示は変わらない
テーブルの利用(3)
… …public TableViewer(String title){ … …
Vector person1 = new Vector(); person1.add("John");
person1.add("male"); person1.add("20");
Vector person2 = new Vector(); person2.add("Mary");
person2.add("female"); person2.add("18");
Vector data = new Vector(); data.add(person1);
data.add(person2);
Vector columnNames = new Vector(); columnNames.add("Name");
columnNames.add("Sex"); columnNames.add("Age");
DefaultTableModel DTM = new DefaultTableModel(data, columnNames); JTable table = new JTable(DTM);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); JScrollPane pane = new JScrollPane();
pane.setViewportView(table); p.add(pane);
add(p, BorderLayout.CENTER);
JTableのコンストラクタ
JTable() -デフォルトの JTable を構築
JTable(int numRows, int numColumns)
- numRows × numColumns で JTable を構築
JTable(Object[][] rowData, Object[] columnNames)
- 2 次元配列 rowData の値をデータ 、 columnNames を列名と するJTableを構築 JTable(TableModel dm) - データモデル dmを基にしたJTable を構築 JTable(TableModel dm, TableColumnModel cm) - データモデル、列モデルを基とした JTable を構築 JTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) - データモデル、列モデル、選択モデルを基としたJTable を構築
JTable(Vector rowData, Vector columnNames)
- Vector型のrowData、columnNames を基としてJTableを構築