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

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

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

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

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

解決済

2回答

1441閲覧

JLayeredPaneの使い方

YUUdesu

総合スコア5

Java

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

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

1グッド

0クリップ

投稿2023/09/06 14:20

実現したいこと

ウィンドウ内に画像を重ねて表示する。

前提

eclipceを使いJAVAでデジタル時計を作ろうと考えJPanel、JFrameを使いウィンドウに画像を表示させるところまではできました。
しかし、二つの画像を用意し重ねて表示しようとすると先に表示されている画像が消えてしまいました。
そこで調べたところJLayeredPaneを使うと重ねて表示できるかもしれないと分かりました。
しかし実際に使ってみると重ねるどころか画像一枚も表示できませんでした。
書き方もよく分からないため教えていただきたいです。

該当のソースコード

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Image;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;

public class window2 extends JFrame{

public window2(String name,int x,int y){ //ウィンドウ作成のコンストラクタ super(name); setSize(x,y); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void WV() { //ウィンドウの可視化 setVisible(true); } public void gazou(String a,int x,int y) { //ウィンドウに画像を貼り付ける(String aは画像のパス) JPanel panel = new JPanel(); JLabel label = new JLabel(); ImageIcon A = new ImageIcon(a); Image I = A.getImage().getScaledInstance(x, y, 1);//画像の大きさ変更 ImageIcon icon = new ImageIcon(I); label.setIcon(icon); panel.add(label); JLayeredPane layer = getLayeredPane(); layer.add(panel,BorderLayout.CENTER); }

public class gazou {

private String a;

gazou(String a){   //画像のパスを格納する
this.a = a;
}
public String GP(){ //画像のパスを返すメソッド
return a;
}

}

public class mine {

public static void main(String[] args) { window2 W = new window2("test",490,485); gazou p = new gazou("C:\\Users\\yuu19\\Downloads\\eclipce\\workspace\\pokecchi\\image\\ぽけっち.png"); W.gazou(p.GP(),500,450); W.WV(); }

}

試したこと

いろいろな書き方を試してみたのですがウィンドウが作られるだけで画像は表示されませんでした。

画像一枚ならcontentPaneを使って表示できたのでその部分をLayerdpaneに変えたバージョンのプログラムを載せておきます。

プログラミングの基礎を学んだばかりの初心者の為もしかしたらかなり訳の分からないことをしているかもしれませんが、もしわかる方がいたら教えていただけるとありがたいです。

silver_night👍を押しています

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

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

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

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

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

jimbe

2023/09/06 14:30 編集

とりあえず、コードのご提示には(ファイル毎に)コードのマークダウン(前後を ``` の行で囲む)をご利用ください。 正しく出来ればコードが専用の枠に囲まれるはずですので、プレビューを見ながら試してみてください。
guest

回答2

0

ウィンドウ内に画像を重ねて表示する。

だけならレイアウトマネージャーを無効にするのが手っ取り早くないですか(別にJLayeredPane使ってもいいですけど)
座標指定で配置する - レイアウトマネージャーを無効にする - Swing

java

1import javax.swing.*; 2import java.net.MalformedURLException; 3import java.net.URL; 4 5public class Window2 extends JFrame { 6 public static void main(String[] args) throws MalformedURLException { 7 new Window2().setVisible(true); 8 } 9 10 Window2() throws MalformedURLException { 11 setSize(300, 300); 12 setLocationRelativeTo(null); 13 setDefaultCloseOperation(EXIT_ON_CLOSE); 14 15 var panel = new JPanel(null); 16 add(panel); 17 18// var label1 = new JLabel(new ImageIcon("C:\\Users\\yuu19\\Downloads\\eclipce\\workspace\\pokecchi\\image\\ぽけっち.png")); 19 var label1 = new JLabel(new ImageIcon(new URL("https://www.gravatar.com/avatar/4c623b6cd8fe491058d7392904f8dcc7?d=identicon"))); 20 label1.setBounds(50, 50, 80, 80); 21 panel.add(label1); 22 23 var label2 = new JLabel(new ImageIcon(new URL("https://teratail-v2.storage.googleapis.com/uploads/avatars/u13/132786/KnkDDC5A_thumbnail.jpg"))); 24 label2.setBounds(10, 10, 80, 80); 25 panel.add(label2); 26 } 27}

Component#setBounds (Java Platform SE 8 )

注意

  • 先に追加したものがになります
  • throws MalformedURLExceptionは、ローカル画像を使うなら不要です

アプリ画像

投稿2023/09/06 16:23

TN8001

総合スコア10002

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

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

YUUdesu

2023/09/07 16:03

レイアウトマネージャーを無効にすると重ねられるんですね! その方法で少し試してみます。 独学でJAVAの基礎を勉強し終わってアプリケーションを作ってみようという段階で、なかなか欲しい情報がうまく手に入れられなかったので助かります。 ありがとうございました。
guest

0

ベストアンサー

古いサイトからですが → レイヤペイン

↑アプレットをアプリケーションにしたものです↓

MainFrame.java

java

1import java.util.Random; 2 3import javax.swing.*; 4 5public class MainFrame extends JFrame { 6 public static void main(String[] args) { 7 SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true)); 8 } 9 10 MainFrame() { 11 super("test"); 12 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 13 setSize(400, 400); 14 15 JLayeredPane layerPane = new JLayeredPane(); 16 layerPane.setLayout(null); 17 18 Random random = new Random(); 19 for(int i=0, x=0, y=0; i<5; i++, x+=20, y+=40) { 20 int layer = random.nextInt(400); 21 JButton button = new JButton("レイヤ : " + layer); 22 button.setBounds(x, y, 200, 50); 23 layerPane.add(button); 24 layerPane.setLayer(button, layer); 25 } 26 27 setContentPane(layerPane); 28 } 29}

実行結果

getLayeredPane で得られるオブジェクトは Swing 自身がダイアログ等を管理する為に使っているものでしょうから、アプリで特別に必要で無ければ直接使うのは避けたほうが良いと思います。
またその JLayeredPane は ContentPane の外に有りますので、それだけで作ると ContentPane が空ということになり、 JFrame が最小になります。

全く関係ありませんが、 java の命名規則等は知っておいたほうが良いと思います。
java ではクラス名は大文字で始め、変数名は小文字で始めることが推奨です。
class windowsclass Window2
window2 W = ~Window2 w = ~
メソッド名は動詞+名詞で小文字始まり、意味が分からなくなる程の過度の省略はしないほうが良いです。
String GP() { ~ }String getPath() { ~ }
強制ではありませんが、開発ツールによっては注意されたり、他人に見せる際に違和感を持たれてそれがコードを読む邪魔になったりします。


時計です。

java

1import java.awt.*; 2import java.text.SimpleDateFormat; 3import java.util.Date; 4import java.util.concurrent.*; 5 6import javax.swing.*; 7 8public class MainFrame extends JFrame { 9 public static void main(String[] args) { 10 SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true)); 11 } 12 13 MainFrame() { 14 super("test"); 15 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 16 17 String filename = "C:\\Users\\Jimbe\\Desktop\\艦これ画像\\Tuscaloosa.png"; 18 //String filename = "C:\\Users\\yuu19\\Downloads\\eclipce\\workspace\\pokecchi\\image\\ぽけっち.png"; 19 Image image = Toolkit.getDefaultToolkit().createImage(filename); //.getScaledInstance(500, 450, Image.SCALE_DEFAULT); 20 JLabel backgroundLabel = new JLabel(new ImageIcon(image)); 21 22 JLabel timeLabel = new JLabel("00:00:00"); 23 timeLabel.setOpaque(false); 24 timeLabel.setFont(timeLabel.getFont().deriveFont(100f)); 25 timeLabel.setForeground(Color.GREEN); 26 27 JLayeredPane layerPane = new JLayeredPane(); 28 layerPane.setLayout(new GridBagLayout()); 29 30 GridBagConstraints gbc = new GridBagConstraints(); 31 gbc.gridx = 0; 32 gbc.gridy = 0; 33 34 layerPane.add(backgroundLabel, gbc); 35 layerPane.setLayer(backgroundLabel, JLayeredPane.DEFAULT_LAYER); 36 37 layerPane.add(timeLabel, gbc); 38 layerPane.setLayer(timeLabel, JLayeredPane.DEFAULT_LAYER + 1); 39 40 setContentPane(layerPane); 41 pack(); 42 setLocationRelativeTo(null); 43 44 SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss"); 45 ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); 46 executor.scheduleAtFixedRate(() -> { 47 SwingUtilities.invokeLater(() -> timeLabel.setText(formatter.format(new Date()))); 48 }, 0L, 1L, TimeUnit.SECONDS); //1秒毎に実行 49 } 50}

実行

質問は JLayeredPane ですので以下は余談となりますが。
ただ二つを重ねるだけであれば、 TN8001 さん回答の注意として書かれている「先に追加したものがになります」が有効(?)に使えます。
この Z オーダーの動作はレイアウトマネージャの設定 (null かどうか ) には関係ありません。
レイアウトマネージャは各コンポーネントの X, Y, Width, Height を管理して 重ならないような 配置をするのが主な役割だからで、重ならせる為にレイアウトマネージャを null にするという方法があるだけです。
(一部のレイアウトマネージャは重ならせることが出来ます。 GridBagLayout がその 1 つです。)
ですから回答コードの 27~38行目を以下のようにすることで、 JLayeredPane を使わなくても (JPanel で ) 重ねられます。
(timeLabel の add と backgroundLabel の add が回答コードと入れ替わっているので注意.)

java

1 //JLayeredPane layerPane = new JLayeredPane(); //★コメント化 2 //layerPane.setLayout(new GridBagLayout()); //★コメント化 3 JPanel layerPane = new JPanel(new GridBagLayout()); //☆追加 4 5 GridBagConstraints gbc = new GridBagConstraints(); 6 gbc.gridx = 0; 7 gbc.gridy = 0; 8 9 layerPane.add(timeLabel, gbc); //☆ 上になるものを先に add する 10 //layerPane.setLayer(timeLabel, JLayeredPane.DEFAULT_LAYER + 1); //★コメント化 11 12 layerPane.add(backgroundLabel, gbc); //☆ 下になるものを後に add する 13 //layerPane.setLayer(backgroundLabel, JLayeredPane.DEFAULT_LAYER); //★コメント化

投稿2023/09/06 15:16

編集2023/09/10 06:29
jimbe

総合スコア13318

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

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

YUUdesu

2023/09/07 16:14

命名規則については申し訳ございません。基礎を勉強している中でそのような話を聞いたことがあったのですが、プログラミングは趣味でのみ行うつもりだったのであまり気にしていませんでした。このような質問サイトを利用することを考え今後は気をつけます。 さて、JLayerdPaneについてですが教えていただいたコードを試したところ当然ですが同じように表示されました。ですが、それを基にいろいろ自分の書いたプログラムを直してみたのですが結局どこを直すのかがよく分かりませんでした。もしよろしければ気になるので少し詳しく教えていただけませんか? 多分、回答してくださった中の「JLayeredPane は ContentPane の外に有りますので、それだけで作ると ContentPane が空ということになり、 JFrame が最小になります。」この部分が上手くいかない原因ということだと思うのですが「JFrameが最小」というのがどういうことかよく分からなかったです。 最終的には指摘のあった通りJLayerPaneは使わず他の回答にあった方法でアプリは作っていこうと思います。
jimbe

2023/09/07 18:55

私もプログラミングは趣味で始めました。考えたものが動くのは楽しいですね(^^ 命名規則的等は、仰る通り全く他人に見せないならどんな書き方でも問題ありませんが、見せないとしても書き方の中には間違え難くして無駄なバグの発生を抑えるカタチとか、ツールの要求として標準とされる書き方が求められたりもあります。 他人のコードを読む際にも共通の土台があれば辞書を単語毎に引くような難しさ/面倒さが少なくより安易に読めると思います。 JFrame が最小というのは、 setSize をしなかった場合のことでした。言葉が足りずすいません。 JLayeredPane が ContentPane の外と言うのは、 JFrame の getLayeredPane で取り出したオブジェクトのことで、 Swing はこのオブジェクトの各レイヤーを使ってダイアログやドラッグ&ドロップ等の表示を行っています。 もしコレが ContentPane に設定されているとしたら、 setContentPane で JLayeredPane 以外のコンテナを設定したら、ダイアログ等が表示出来なくなるでしょう。しかし祖のようなことになったことはありません。 なら、コレは JFrame から ContenrPane の間のあり ContentPane はコレのデフォルトレイヤーに乗ると考えると、ビューの階層構造がスッキリします。 また、 JLayeredPane はデフォルトのレイアウトマネージャを持ちません(null)。従ってどのレイヤーにコンポーネントを置いても JLayeredPane の大きさは 0 として扱われます。 ContentPane (とsetSize )が無ければ最小になるのはこのような為です。 ではレイアウトマネージャを設定すれば良いのかというと状況によります。 JLayeredPane のドキュメントにも書いてありますが、レイアウトマネージャを設定するとそれはレイヤーに関係無く全てのコンポーネントの配置に使われます。もしその設定先が getLayeredPane で得たものなら、例えばダイアログを表示するとその位置・大きさもレイアウトマネージャが影響するということです。 そうでなくても、 BorderLayout を設定して 2 つのコンポーネント(レイヤーは違う)を中央で重ねようと add(component1, BorderLayout.CENTER); add(component2, BorderLayout.CENTER); としても、 BorderLayout は1ヶ所には1つしか表示させない為、重なった表示はなりません。 このような諸々がありまして、1つには getLayeredPane ではなく新たにオブジェクトを作って ContentPane として設定して使うことが必要となっています。
jimbe

2023/09/07 19:21 編集

レイアウトマネージャを null にすることで重ねるというのは、 Swing としては行儀のよいものでは無いことは知っていた方が良いと思います。 レイアウトマネージャの役割は、フレームやコンポーネントの大きさの変化等に連動して各コンポーネントの位置・大きさを自動で調節することです。言わば自動運転機能みたいなもので、それを止めるなら代わりに全てを手動で行い・対応しなければなりません。 勿論、状況が単純であれば大した手間はありません。ウインドウやコンポーネントの大きさは一定値で変わらない/変えられないとかです。 ですが、 GUI である Swing アプリなのにウインドウの大きさが変えられないとか、何か違うのではないでしょうか。 参考までに、画像を背景にした時計を作りましたので回答に追加しておきます。 画像が背景1つですので『二つの画像を用意し重ねて表示』するというデジタル時計には及ばないと思いますが、レイアウトマネージャを使って画像の大きさのウインドウを作っています。ウインドウの大きさを変えても画像と時計は中央にあります。
YUUdesu

2023/09/08 13:03

わざわざ時計の参考プログラムまで作っていいただきありがとうございます! 実際に作りたいものとほぼ同じようなものでとても参考になります! JAVAの基礎的なことはネット上にたくさん簡単に理解できるよう解説されているのですが、Swingなどの発展したものについては、調べても内容が難しかったり、APIドキュメントを見てもまだ上手く理解できないことが多かったので非常に勉強になりました。 教えていただいたことを基に完成を目指します! 長文で解説していただき本当にありがとうございました。
jimbe

2023/09/09 19:20

コンピュータの世界は日進月歩で日々情報が増えていきますから、後から始めようとすれば先に始めた場合と比べれば時間の分だけ情報が大量になります。 また、 Swing は java でアプリケーションを書くためのものですが、当時から既にネットワーク越しのシステムが出来始めていましたし、 java より簡単なスクリプト系言語やタブレット・スマホ等の環境の登場もあって普及しないまま半ば放置状態になり(後発の javaFX は既にありませんし)、従ってより扱い易くするとかいう発展がされていないので、難しいままになってしまっているという感じがします。 返ってスマホ(android) で java で何か作るほうが、今は解説等が多いかもしれません。まぁ、android も java より kotlin になってきているので、どこまで java の情報が残るか分かりませんが。
YUUdesu

2023/09/11 02:44

あれからさらに色々な解説ありがとうございます。 GridBagLayoutについては知らなかったのでネットで調べて勉強してみました。 一口にコンポーネントを重ねるといっても様々なやり方があり、どれが適してるかといった判断をするのはなかなか難しいですね。 先日本屋さんにいってSwingなどのクラスライブラリについての書籍がないか探してみたのですが基礎についての本が多く実践的な本だと多分JAVA単体ではなく他のシステムとの併用方法的なことが書かれていてなかなか勉強するのが難しいと感じました。 皆さんどのように勉強されているのかが気になります。
jimbe

2023/09/11 03:46

私が使うマネージャはほぼ BorderLayout か GridBagLayout です。 重ねるというと CardLayout もありますが、重ねるというよりは切り替え(入れ替え)ですね。 今書店で "java" というとサーブレットか android かでしょうか。 swing 関係の本なら、書店よりも図書館かもしれません (=.=
YUUdesu

2023/09/12 11:56

様々なレイアウトマネージャーを使えるようになると便利そうですね! まさしくその辺りについての本ばかりでしたね。 まぁしばらくJAVAだけで遊んだらその辺りも勉強しようと思ってるんですけどね。 確かに地域の大きめの図書館に行けば割と知りたいことが知れるかもしれないですね! アドバイスありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.32%

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

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

質問する

関連した質問