1
第3回複雑なレイアウトのイベント処理、画像データの読込み、テーブルの使用
キーポイント• レイアウトについて
– 前回までのレイアウト
– レイアウトの補足機能
– 固定座標を用いたレイアウト
– Grid Layout
• CardLayoutについて– Card Layout
– Card Layoutによる複数ページ表示
• ファイルの読み込み– JFileChooserクラス
– java.awt.FileDialog
– 画像データの読み込みと表示
• テーブルの利用– JTableクラス
– テーブルデータの初期設定
– Vector型データの使用
前回までに学んだGUIのレイアウト
• BorderLayout、FlowLayoutなどの標準的なレイアウトを学んだ
• 今回は、更に複雑なデザインのGUIを作るためのレイアウト、またそれに伴うイベント処理について学習していく
2
BorderLayout
FlowLayout
基本的なレイアウトの補足• フレームのサイズを固定する
– setResizable()メソッドを用いて、引数にfalseを与えることでフレームのサイズを固定する
3
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アプリケーションは色々な環境で実行される可能性があるため、基本的にはレイアウトマネージャの使用が推奨されるが、座標指定でアプリケーションを作成した場合などは固定座標を用いる
5
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クラスの持つメソッドは以下の通り
7
first() - コンテナの最初のカードに切り替えるlast() - コンテナの最後のカードに切り替えるnext() -指定されたコンテナの次のカードに切り替えるprevious() -指定されたコンテナの前のカードに切り替える
next() next() next()
previous() previous() previous()
first() … … last()
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)• カード移動用のボタンとイベントの追加を行う
9
… …
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 2 extends JFrame
implements 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)• 実行して画面の動作を確認
11
First
jps[0] jps[1]
jps[2] jps[3]
Last
next
Prev
ファイルの読み込み(1)• JFileChooserクラスを用いたファイルの読み込み
– 画面上でファイル名を選択できるダイアログを表示する場合に利用する
12
public class JFileChooserTest extends JFrame
implements 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クラスを用いたファイルの読み込み
– 画面上でファイル名を選択できるダイアログを表示する場合に利用する
13
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 「取消し」ボタンが選択された場合
JFileCHooser.ERROR_
OPTION-1 エラー発生時
ファイルの読み込み(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クラスを用いて画像の表示をする
15
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",
FileDialog.LOAD);
}
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クラスは表形式の形でデータを表示する際に使用する
– データベースのデータのように扱うために、同じ列のデータはデータ形式を統一する必要がある
17
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)
19
… …
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を構築
• テーブルのデータの扱い– 前項では配列を用いてテーブルを作成した
– 配列ではなく、Vector型のオブジェクトを用いてテーブルを作成することもできる
テーブルの利用(4)
20
… …
public TableViewer(String title){
… …
// テーブルにデータを与えるための引数として、// Vector型のオブジェクトを作成するVector tabledata = new Vector();
tabledata.add("HoseiTaro");
tabledata.add("male");
tabledata.add("24");
// DefaultTableModelクラスのaddRow()クラスを使って// データを後から追加することができるDTM.addRow(tabledata);
… …
}
• テーブルデータを追加する– addRow() メソッドを使ってテーブルにデータを追加することができる
– 以下の記述を付け足して実行し、動作を確認して下さい
DefaultTableModelクラスのaddRow()メソッドを使って後から追加したデータが、実際に追加されていることを確認することができる
このようにして、初期値を与えたテーブルに後からデータを追加することができる
Top Related