🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Java

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

UI

UIはUser Interfaceの略であり、人間がコンピュータとやりとりをするためのシステムです。

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

Eclipse

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

Q&A

解決済

1回答

1842閲覧

scrollPaneでチャットメッセージ的なものを実現したい(イメージはLINEのチャット)

Jhon_McClane

総合スコア48

Java

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

UI

UIはUser Interfaceの略であり、人間がコンピュータとやりとりをするためのシステムです。

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

Eclipse

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

1グッド

0クリップ

投稿2020/12/13 09:41

編集2020/12/16 09:27

前提・実現したいこと

上記課題に補足。現在チャットメッセージを開発しています.
まだまだ初期段階でいろいろ試行錯誤している状態です.GUIに関しては初心者です.

実現したいことは1つのメッセージ単位を後からどんどん追加していって,前のメッセージが上にたまっていくものを作りたいです.

JPanelに画像とボタン数種類を付加したものを一つのメッセージとしてパネル単位でメッセージ枠を作り、JScrollPaneクラスで実現しようと考えています.
今のところ,「JScrollPaneクラスは単独で用いるものではなく他のコンポーネントにスクロール機能を提供するもの」ということは分かりました.

完成イメージです.
イメージ説明

発生している問題

現段階では送信ボタンを押すと,メッセージを出すようにしているのですが,その描画が反映されない状況です。
また,送信ボタン周りの操作クラスが再描画によってつぶれてしまい,適切な領域が割り当てられていなく,スクロールもない状態になってしまっています.
ChatBounddaryの継承をJPanelに変更したことで,add(scrollPane, BorderLayout.CENTER);を書く適切な位置がわからなくなってしまいました.

該当のソースコード

package boundary; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; public class Message extends JPanel implements MouseListener, ActionListener { private EmotionButton[] eb = new EmotionButton[4]; private ImageIcon[] icon = new ImageIcon[4]; //private static final int WIDTH = 900; //private static final int HEIGHT = 900; private JButton saveBtn; public Message(String imageName,FlowLayout layout) { setLayout(layout); setBackground(Color.WHITE); //setPreferredSize(new Dimension(WIDTH, HEIGHT)); //setBackground(Color.black); ImageIcon image = new ImageIcon(imageName); JLabel jl = new JLabel(image,JLabel.CENTER); add(jl); for (int i = 0; i < 4; i++) { icon[i] = new ImageIcon("emotion" + i + ".png"); eb[i] = new EmotionButton(icon[i]); eb[i].setPreferredSize(new Dimension(100, 100)); eb[i].addMouseListener(this); add(eb[i]); } saveBtn = new JButton("保存"); saveBtn.addActionListener(this); add(saveBtn, BorderLayout.EAST); } public void paintComponent(Graphics g) { super.paintComponent(g); } public void actionPerformed(ActionEvent e) { InformDialog.displayDialogText("保存します"); } public void mouseClicked(MouseEvent e) { EmotionButton eBtn = (EmotionButton) e.getSource(); switch (e.getButton()) { case MouseEvent.BUTTON1: eBtn.setText(String.valueOf(eBtn.editBtn("wataru"))); break; case MouseEvent.BUTTON3: ArrayList<String> arrUN = eBtn.getUserName(); for (int i = 0; i < arrUN.size(); i++) { System.out.println(arrUN.get(i)); } if (arrUN.size() != 0) { InformDialog.displayDialogText(arrUN.get(0)); } break; } } public void mouseEntered(MouseEvent e) { //InformDialog.displayDialogText("ボタンに触れましました。"); } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } }
package boundary; import javax.swing.JFrame; public class Main extends JFrame{ public static void main(String[] args) { Main frame = new Main(); frame.setTitle("画面遷移テスト"); frame.setSize(2200, 1400); frame.setLocationRelativeTo(null); ChatBoundary chatBoundary = new ChatBoundary(); frame.getContentPane().add(chatBoundary); frame.setVisible(true); } }
package boundary; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; public class ChatBoundary extends JPanel{ private static final FlowLayout right = new FlowLayout(FlowLayout.RIGHT); private static final FlowLayout left = new FlowLayout(FlowLayout.LEFT); public ChatBoundary(){ setLayout(new BorderLayout()); setPreferredSize(new Dimension(2200, 1200)); setBackground(Color.black); // メッセージが追加されていく本体 Box inner = Box.createVerticalBox(); inner.setBorder(BorderFactory.createLineBorder(Color.RED, 5)); //JPanel outer = new JPanel(new BorderLayout()); //outer.add(inner, BorderLayout.NORTH); //outer.setBorder(BorderFactory.createLineBorder(Color.GREEN, 5)); add(inner, BorderLayout.NORTH); setBorder(BorderFactory.createLineBorder(Color.GREEN, 5)); //JScrollPane scrollPane = new JScrollPane(outer); JScrollPane scrollPane = new JScrollPane(this); //add(scrollPane, BorderLayout.CENTER); scrollPane.setBorder(BorderFactory.createLineBorder(Color.BLUE, 5)); scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { private int max = scrollPane.getVerticalScrollBar().getMaximum(); public void adjustmentValueChanged(AdjustmentEvent e) { if (max - e.getAdjustable().getMaximum() == 0) return; e.getAdjustable().setValue(e.getAdjustable().getMaximum()); max = scrollPane.getVerticalScrollBar().getMaximum(); } }); JPanel controls = new JPanel(); // 操作エリア add(controls, BorderLayout.SOUTH); JTextField textField = new JTextField("メッセージ", 20); controls.add(textField); textField.selectAll(); // 全選択 JButton button = new JButton("送信"); controls.add(button); button.addActionListener(e -> { inner.add(new Message("naruto.jpg", right)); inner.add(Box.createVerticalStrut(10)); // 隙間 inner.add(new Message("naruto.jpg", left)); inner.add(Box.createVerticalStrut(10)); // 隙間 scrollPane.revalidate(); // 再描画 textField.selectAll(); // 全選択 textField.requestFocus(); // フォーカス }); textField.addActionListener(e -> button.doClick()); } }
package boundary; import java.util.ArrayList; import javax.swing.ImageIcon; import javax.swing.JButton; //メッセージのエモーションにかかわるボタンの処理クラス class EmotionButton extends JButton { private ArrayList<String> arrL = new ArrayList<String>(); public EmotionButton(ImageIcon icon) { super("0", icon); } public int editBtn(String userName) { if(arrL.contains(userName)) { arrL.remove(arrL.indexOf(userName)); return arrL.size(); } else { arrL.add(userName); return arrL.size(); } } public ArrayList<String> getUserName() { return arrL; } }

補足情報(FW/ツールのバージョンなど)

eclipse 2020/12/9にダウンロードしたため最新だと思います.
java8です.
基本swingを用いて開発します.

TN8001👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

GUIは難しいですね。レイアウトが思ったようにできないとイライラします(しました^^;

チャットメッセージ的なものを実現したい

元コードの意図がわからなかったので、跡形もないですがこういうのですよね?

上に詰めつつスクロールさせるところで、ちょっとトリックがあります。
構造がわかりやすいようにボーダーを付けましたが、理解できたら消してください。

Java

1import java.awt.BorderLayout; 2import java.awt.Color; 3import java.awt.FlowLayout; 4import java.awt.event.AdjustmentEvent; 5import java.awt.event.AdjustmentListener; 6import java.io.IOException; 7import java.net.URL; 8import java.util.Random; 9import javax.imageio.ImageIO; 10import javax.swing.BorderFactory; 11import javax.swing.Box; 12import javax.swing.ImageIcon; 13import javax.swing.JButton; 14import javax.swing.JFrame; 15import javax.swing.JLabel; 16import javax.swing.JPanel; 17import javax.swing.JScrollPane; 18import javax.swing.JTextField; 19 20public class ChatBoundary extends JFrame { 21 public static void main(String[] args) { 22 new ChatBoundary().setVisible(true); 23 } 24 25 private static final String image1 = "https://teratail-v2.storage.googleapis.com/uploads/avatars/u12/122491/3405b8776c1faabf_thumbnail_32x32.png"; 26 private static final String image2 = "https://teratail-v2.storage.googleapis.com/uploads/avatars/u13/132786/KnkDDC5A_thumbnail_32x32.jpg"; 27 private static final FlowLayout right = new FlowLayout(FlowLayout.RIGHT); 28 private static final FlowLayout left = new FlowLayout(FlowLayout.LEFT); 29 30 private ImageIcon icon1; 31 private ImageIcon icon2; 32 33 ChatBoundary() { 34 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 35 setSize(400, 600); 36 setLocationRelativeTo(null); 37 38 try { 39 icon1 = new ImageIcon(ImageIO.read(new URL(image1))); 40 icon2 = new ImageIcon(ImageIO.read(new URL(image2))); 41 } catch (IOException e) { 42 e.printStackTrace(); 43 } 44 45 // メッセージが追加されていく本体 46 Box inner = Box.createVerticalBox(); 47 inner.setBorder(BorderFactory.createLineBorder(Color.RED, 5)); 48 49 // うまく説明できないがinnerがエリア全体を占めないようにするため 50 // BorderLayout.NORTHで上に詰めるようにダミーのパネル(セコいw 51 // ↓こちらではGlueで調整しているが、「それもどうなの?」という気がする 52 // [BoxLayoutでリスト状に並べる - Java Swing Tips](https://ateraimemo.com/Swing/ComponentList.html) 53 JPanel outer = new JPanel(new BorderLayout()); 54 outer.add(inner, BorderLayout.NORTH); 55 outer.setBorder(BorderFactory.createLineBorder(Color.GREEN, 5)); 56 57 //JScrollPane scrollPane = new JScrollPane(inner); 58 // ↓のかわりに↑にしてみてください。「そうじゃないんだよ!」というのがわかります 59 JScrollPane scrollPane = new JScrollPane(outer); 60 add(scrollPane, BorderLayout.CENTER); 61 scrollPane.setBorder(BorderFactory.createLineBorder(Color.BLUE, 5)); 62 63 // 自動スクロール [java - JScrollPane and JList auto scroll - Stack Overflow](https://stackoverflow.com/questions/2132444/jscrollpane-and-jlist-auto-scroll/52539517#52539517) 64 scrollPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { 65 private int max = scrollPane.getVerticalScrollBar().getMaximum(); 66 67 public void adjustmentValueChanged(AdjustmentEvent e) { 68 if (max - e.getAdjustable().getMaximum() == 0) return; 69 70 e.getAdjustable().setValue(e.getAdjustable().getMaximum()); 71 max = scrollPane.getVerticalScrollBar().getMaximum(); 72 } 73 }); 74 75 JPanel controls = new JPanel(); // 操作エリア 76 add(controls, BorderLayout.SOUTH); 77 78 JTextField textField = new JTextField("メッセージ", 20); 79 controls.add(textField); 80 textField.selectAll(); // 全選択 81 82 JButton button = new JButton("送信"); 83 controls.add(button); 84 button.addActionListener(e -> { 85 inner.add(new Message(textField.getText(), icon1, right)); 86 inner.add(Box.createVerticalStrut(10)); // 隙間 87 88 inner.add(new Message(getResponse(), icon2, left)); 89 inner.add(Box.createVerticalStrut(10)); 90 91 scrollPane.revalidate(); // 再描画 92 93 textField.selectAll(); // 全選択 94 textField.requestFocus(); // フォーカス 95 }); 96 97 textField.addActionListener(e -> button.doClick()); // エンターキーで送信 98 } 99 100 // 特に意味はない チャット感を出すため 101 private String[] responses = { "なるほどね", "ふーん", "知ってた", "おk" }; 102 private Random random = new Random(); 103 104 private String getResponse() { 105 return responses[random.nextInt(responses.length)]; 106 } 107 108 109 static class Message extends JPanel { 110 public Message(String message, ImageIcon icon, FlowLayout layout) { 111 setLayout(layout); 112 setBackground(Color.WHITE); 113 114 add(new JLabel(message, icon, JLabel.CENTER)); 115 JButton button = new JButton("\uD83D\uDC4D"); 116 button.addActionListener(e -> System.out.println(message + "をいいねしました")); 117 add(button); 118 } 119 } 120}

アプリ画像


サンプル追記

Java

1static class Message extends JPanel { 2 public Message(String message, ImageIcon icon, FlowLayout layout) { 3 setLayout(layout); 4 setBackground(Color.WHITE); 5 6 JPanel panel = new JPanel(); 7 panel.add(new JLabel(icon)); 8 9 JPanel p1 = new JPanel(); 10 // 雑い フォントサイズによりずれると思われる 11 p1.setPreferredSize(new Dimension(170,70)); 12 p1.add(new JButton("\uD83D\uDE00")); 13 p1.add(new JButton("\uD83D\uDE11")); 14 p1.add(new JButton("\uD83D\uDE0D")); 15 p1.add(new JButton("保存")); 16 17 panel.add(p1); 18 add(panel); 19 } 20}

投稿2020/12/13 21:12

編集2020/12/16 09:57
TN8001

総合スコア9855

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

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

Jhon_McClane

2020/12/16 04:22

返信遅れて申し訳ありません。GUIについてわからないことがあった場合ご連絡するかもしれませんので、その際はよろしくお願いします。少し時間がかかるかもしれませんが...
TN8001

2020/12/16 05:02

画像にあるようなものが、所望のものということでいいんですね? コピペで動かせるようになっていますが、動かしていただけましたか? 結構説明を入れたつもりですが、分かりにくいところがありますか? ポイントは赤緑青3色のボーダーがあるように、3重構造になっているところです。 実行してアイテムが空の時から増えていくにしたがって、どうなるかを確認してください(特にinner 赤) コメントにあるように、outerがなかった場合も確認してください。 動かしてみれば「あぁ、そうじゃないね」と一目でわかります。 自動スクロールやJTextFieldの全選択・フォーカス・エンターでクリックは、本題でないので省いても結構です(実用上はないと不便だと思い、入れておきましたが)
Jhon_McClane

2020/12/16 06:35

画像にあるようなものが、所望のものということでいいんですね? →TN8001さん、本当の完成イメージ図を写真に載せました。今作っているアプリは画像を送りあうというもので、テキストからは画像を直接ドラック&ドロップするものと、参照するものの2つの要素を含んでいます。テキストフィールドから文字は打つ予定はありません。 コピペで動かせるようになっていますが、動かしていただけましたか? →動作イメージはouterを自分はイメージしていました。写真のイメージはMessageを真ん中よりに書いてしまいましたが、自分と他人で右寄りか左寄りにしたいです。
TN8001

2020/12/16 09:58

>本当の完成イメージ図を写真に載せました。 class Messageが1つのアイテムですので、それを好きなように変えてください。 雑ですがサンプルを追記しました。 >画像を送りあう >画像を直接ドラック&ドロップする は、もう質問からかけ離れているので、別に質問を立ててください。 作成代行サイトではないので、詰まっている点をはっきりさせたうえでお願いします。 >動作イメージはouterを自分はイメージしていました。 そうですか^^; ならinnerなしにすればいいですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問