質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

2121閲覧

java:frameは使いまわし、panelを描画・削除してページ遷移したいです

makoto-n

総合スコア436

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2019/01/02 18:36

編集2019/01/06 02:30

javaでアプリケーション作成中です。
ページ遷移をしたいのですが、frameを消してnewをして~を繰り返しては移動させたframeが初期の位置に戻ってしまいます。
なのでpanelに部品を埋め込み、遷移するさいにはpanelをremoveAllして新規panelをnewしたいと思ったのですが、
panelを消せずに詰まっています。
どうか改善点・または別の案を押してください。

java

1 2import java.awt.BorderLayout; 3import java.awt.Container; 4import java.awt.event.ActionEvent; 5 6import javax.swing.JButton; 7import javax.swing.JFrame; 8import javax.swing.JPanel; 9import javax.swing.JTextField; 10 11class SSample3_1 extends JFrame { 12 JButton btn1, btn2, btn3, btn4; 13 JPanel p; 14 SSample3_1 dodai2; 15 16 public static void main(String args[]) { 17 SSample3_1 frame = new SSample3_1("タイトル"); 18 frame.setVisible(true); 19 } 20 21 SSample3_1(String title) { 22 setTitle(title); 23 setBounds(100, 100, 300, 250); 24 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 25 26 p = new JPanel(); 27 28 btn1 = new JButton("Button"); 29 btn2 = new JButton("Button"); 30 btn3 = new JButton("Button"); 31 32 p.add(btn1); 33 p.add(btn2); 34 p.add(btn3); 35 36 btn1.addActionListener(null); 37 btn2.addActionListener(null); 38 btn3.addActionListener(null); 39 40 Container contentPane = getContentPane(); 41 contentPane.add(p, BorderLayout.CENTER); 42 } 43 private void junbi2() { 44 45 JTextField text1 = new JTextField(); 46 text1.setText("aaaaa"); 47 48 p.add(text1); 49 setDefaultCloseOperation(EXIT_ON_CLOSE); 50 51 } 52 53 public void actionPerformed(ActionEvent e) { 54 if (e.getSource() == btn1) { 55 p.removeAll(); 56 dodai2 = new SSample3_1("title"); 57 this.junbi2(); 58 dodai2.setVisible(true); 59 } else if (e.getSource() == btn2) { 60 p.removeAll(); 61 } else if (e.getSource() == btn3) { 62 p.removeAll(); 63 } 64 } 65}

removeAllです。失礼しました。

イベントを追加についてですが、
btn1.addActionListener(null)
をthisに変更するとEclipseではエラーになってしまいます。
イベントはゆくゆくは別のファイルに記述したいと考えておりますが、
現状は汚くても実装させることを先に考えています。

btn1...にイベントをaddできてもいません。


(A) インターフェースActionListenerを実装したクラスのインスタンス

java

1package db_test; 2 3import java.awt.BorderLayout; 4import java.awt.Container; 5import java.awt.event.ActionEvent; 6import java.awt.event.ActionListener; 7 8import javax.swing.JButton; 9import javax.swing.JFrame; 10import javax.swing.JPanel; 11import javax.swing.JTextField; 12 13class SSample3_1 extends JFrame implements ActionListener { 14 JButton btn1, btn2, btn3, btn4; 15 JPanel p; 16// SSample3_1 dodai2; 17 18 public static void main(String args[]) { 19 SSample3_1 frame = new SSample3_1("タイトル"); 20 frame.setVisible(true); 21 } 22 23 SSample3_1(String title) { 24 setTitle(title); 25 setBounds(100, 100, 300, 250); 26 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 27 28 p = new JPanel(); 29 30 btn1 = new JButton("Button"); 31 btn2 = new JButton("Button"); 32 btn3 = new JButton("Button"); 33 34 p.add(btn1); 35 p.add(btn2); 36 p.add(btn3); 37 38 btn1.addActionListener(this); 39 btn2.addActionListener(this); 40 btn3.addActionListener(this); 41 42 Container contentPane = getContentPane(); 43 contentPane.add(p, BorderLayout.CENTER); 44 } 45 46 private void junbi2() { 47 48 JTextField text1 = new JTextField(); 49 text1.setText("aaaaa"); 50 51 p.add(text1); 52 setDefaultCloseOperation(EXIT_ON_CLOSE); 53 54 } 55 56 public void actionPerformed(ActionEvent e) { 57 if (e.getSource() == btn1) { 58 this.p.removeAll(); 59 // dodai2 = new SSample3_1("title"); 60 // this.junbi2(); 61 // dodai2.setVisible(true); 62 } else if (e.getSource() == btn2) { 63 p.removeAll(); 64 } else if (e.getSource() == btn3) { 65 p.removeAll(); 66 } 67 } 68}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/01/03 02:44

イベントを登録してないボタンで何をしたいの? 問題のあるイベントを登録した最新のソースを添付してください。
KSwordOfHaste

2019/01/03 03:24

(A)「panelをremoveする」 (B)「panelから全ての子供コンポーネント(ボタン3つのことです)をremoveする」 コードは(B)に見えますが質問文の内容は(A)です。文章は正確にお願いします。読む側が混乱し質問者さんの意図をつかみにくくなります。
makoto-n

2019/01/03 17:33

すみません、問題のあるソースはこれ一つのみです。 イベントを追加できていない、もしくは、remobeAllの使い方が変なのかわかりません。 removeAllです、失礼しました。
guest

回答1

0

ベストアンサー

最初にタイトルの主題から外れた内容であることをお詫びします。

質問内容は画面遷移に関してなのですが、ボタンをクリックした際のActionListenerの登録自体に躓いておられるようでしたのでそこに焦点をあててコメントいたします。

ActionListenerを実装したクラス(あるいはそのインスタンス)

JButtonのメソッドaddActionListenerの引数に指定すべきはActionListenerですがこれはJava言語仕様で「関数型インターフェース(functional interface)」と呼ばれているものです。これに適合するような値の指定方法は見かけ上様々なバリエーションがありますが、本質的には以下の3通りぐらいです。

Java7以前の仕様
(A) インターフェースActionListenerを実装したクラスのインスタンス

Java8で追加された仕様
関数型インターフェースActionListenerの要実装メソッドactionPerformedのシグネチャに適合するような
(B) lambda式
(C) メソッド参照

質問文に「thisに変更すると...エラーになってしまいます」とあります。その書き方は(A)に該当します。しかし質問者さんがそこで躓いたのはクラスが特定のインターフェースを「実装」することの正確な意味を把握しておられないことが原因のようです。

(A)の「実装した」の意味は大雑把に言えば「クラスの宣言部にActionListenerからの継承であることを明記しているもの、あるいはその派生」といえ、SSample3_1の宣言部が

class SSample3_1 implements ActionListener

となっていない点が問題なのです。ここまでは、swingあるいはEclipseの知識ではなくJavaの言語仕様に関する知識です。

swingにおけるActionListenerの指定バリエーション

SSample3_1の宣言部に「implements ActionListener」と書けばとりあえず

btn1.addActionListener(this);

と書けるのですが、単一のクラス(典型的にはJFrameの派生)に複数のボタンのアクションを全部まかせるのはどちらかといえば「悪手」になりかねないと思います。actionPerformedメソッドの中で「どのボタンが押されたかいちいち切り分けなければならない」からです(質問者さんのコードはそうなってます)。

切り分けの煩雑さを避けるためのJava7以前での主要な方法は「名前ありの個別の具象クラス」あるいは「匿名クラス」を用いることでしたが、Java8が出て久しい現在前述の(B)(C)を活用できる機会も多いのではないでしょうか。

java

1 2class MyFrame extends JFrame { // ActionListenerは実装しない 3 JButton button1 = new JButton("button 1"); 4 JButton button2 = new JButton("button 2"); 5 ... 6 7 MyFrame() { 8 ... 9 10 // (1)lambda式(だいたい3行以上にはなる) 11 // 短い処理の場合いちいちメソッドを定義せずに済む。 12 button1.addActionListener(event -> { 13 System.out.println("ボタン1がおされた"); 14 }); 15 16 // (2)メソッド参照(だいたい1行) 17 // アクションの記述が長いとき、lambda式でだらだら書くとアクション登録と 18 // アクション処理本体がごちゃまぜになり画面構築コードの見通しが悪くなりがち。 19 // アクション処理をメソッドに分離した場合はメソッド参照により簡潔に記述できる。 20 button2.addActionListener(this::onClick2); 21 ... 22 23 // (3)lambda式(1行しか要しないパターン) 24 // ActionEventを必要としない場合onClick3の引数を書かずに済ませる目的でこうすることも。 25 button3.addActionListener(e -> onClick3()); 26 ... 27 } 28 29 private void onClick2(ActionEvent e) { 30 // 何行かにわたる長めの処理 31 ... 32 } 33 34 private void onClick3() { 35 // 何行かにわたる長めの処理 36 ... 37 } 38}

上記はイベント処理を実装するのに必要な言語仕様とその応用の一部の紹介にすぎません。実際にコードを書く際にはアクセスしたい情報(変数や別のインスタンス)をどこに定義しておくかなど言語仕様やオブジェクト指向設計のトピックが色々あります。

応用プログラムを書こうとしている段階で「言語仕様の再確認」なんて言われてもまどろっこしく感じると思いますが、基礎をかためておかないと具体的機能(画面遷移とか)に取り組もうとしても迷走しがちだと思います。失礼ながら本Q&Aはそんな印象を持ちました。swingを用いた機能の実現法だけでなくこういう基礎の部分にも目を向けるとよいと思います。

投稿2019/01/04 03:31

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

makoto-n

2019/01/06 02:37

詳しい解説をしていただきありがとうございます。 先にAから取り掛かろうと思いましたの >> (A) インターフェースActionListenerを実装したクラスのインスタンス  class SSample3_1 extends JFrame implements ActionListener を試したところエラーにはならないようです。 が、removeAllが適切ではないのか、ボタンクリック後にパネルが消えません。 仰る「Javaの言語仕様に関する知識」に関するところですが、 すみません、ここで躓いてしまいました。 パネルを消すには this.p.removeAll では不適切でしょうか?
KSwordOfHaste

2019/01/06 02:52 編集

p.removeAllで3つのボタンはパネルの子供コンポーネントではなくなるので方向は間違ってません。しかしswingは「状態が変わっても再描画しないとその結果が画面に反映されないケースがある」という点に注意が必要です。まずは p.removeAll(); p.repaint(); //<=これを追加 としてみてください。画面上からもボタンが消えるはずです。 --- うるさいことをいうようですが「パネルを消す」はちょっと曖昧です。 (A)ウィンドウからそのパネル自体を消すこと (B)そのパネル上にある他の子どもコンポーネントを消す のどちらにも受け取れるからです。プログラミングの会話をする際には「極力正確な表現」を心がけてください。(A)なのか(B)なのかで意味もすべき処理も違いますので。
makoto-n

2019/01/06 05:28

なるほど、ありがとうございます。 特性があったのですね、再描画できました。 (B) lambda式 (C) メソッド参照 について試行錯誤してみようと思います。 また、正確な表現につき助言してくださってありがとうございます、今後に生かします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問