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

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

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

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

Swing

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

Q&A

解決済

1回答

437閲覧

JscrollPaneのsetvalueはなぜswingutilities.invokeでなければ正常に実装できないのか

Mitika-t

総合スコア4

Java

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

Swing

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

0グッド

1クリップ

投稿2023/08/26 20:40

編集2023/08/27 04:09

私は現在swingを使ってメモ帳アプリを作っています
jscrollpaneにtextpaneをaddし
ファイルからテキストデータを読み込みtextpaneに文字列をsettext
するプログラムです
そこでtextpaneをsettextした後に
scrollPane.getVerticalScrollBar().setValue(0)
をよびだし、スクロール位置を最上部に移動させたかったのですが、
実行すると最下部になっていました。
調べた結果以下のコードで適切に実装できました

java

1 Runnable moveScrollBar = new Runnable() { 2 3 @Override 4 public void run() { 5 // TODO 自動生成されたメソッド・スタブ 6 scrollPane.getVerticalScrollBar().setValue(0); 7 } 8 }; 9 SwingUtilities.invokeLater(moveScrollBar);

しかし、動作原理がいまいち理解できていません
なぜinvokelaterを使えば実装できるのか、
直接jscrollbar.setvalue(0);のコードでは
うまくいかないのかを教えて下さい。

コードの全体

java

1public class MemoTool extends JFrame implements ActionListener { 2 public static void main(String[] args) { 3 // TODO 自動生成されたメソッド・スタブ 4 new MemoTool(); 5 } 6 7 JButton saveBtn = new JButton("save"); 8 JButton clearBtn = new JButton("clear"); 9 JTextPane textPane = new JTextPane(); 10 JMenuBar menuBar = new JMenuBar(); 11 JMenu menu = new JMenu("file"); 12 JMenuItem newItem = new JMenuItem("new"); 13 JMenuItem openItem = new JMenuItem("open"); 14 JScrollPane scrollPane = new JScrollPane(textPane); 15 JFileChooser fileChooser = new JFileChooser(); 16 17 MemoTool() { 18 this.setDefaultCloseOperation(EXIT_ON_CLOSE); 19 this.setAlwaysOnTop(true); 20 fileChooser.addChoosableFileFilter(new TextFilter()); 21 22 menu.add(openItem); 23 menu.add(newItem); 24 menuBar.add(menu); 25 this.setJMenuBar(menuBar); 26 openItem.addActionListener(this); 27 newItem.addActionListener(this); 28 29 JPanel p1 = new JPanel(); 30 p1.setLayout(new GridLayout(1, 2)); 31 p1.add(saveBtn); 32 p1.add(clearBtn); 33 saveBtn.addActionListener(this); 34 clearBtn.addActionListener(this); 35 this.getContentPane().add(BorderLayout.SOUTH, p1); 36 37 this.getContentPane().add(BorderLayout.CENTER, scrollPane); 38 39 this.setTitle("メモ帳"); 40 this.setBounds(30, 30, 400, 500); 41 this.setVisible(true); 42 } 43 44 File file = null; 45 46 @Override 47 public void actionPerformed(ActionEvent e) { 48 if (e.getSource() == openItem) { 49 int selected = fileChooser.showOpenDialog(this); 50 if (selected == JFileChooser.APPROVE_OPTION) { 51 file = fileChooser.getSelectedFile(); 52 } else if (selected == JFileChooser.CANCEL_OPTION) { 53 54 } else if (selected == JFileChooser.ERROR_OPTION) { 55 56 } 57 if (file != null) { 58 59 FileReader fr; 60 try { 61 fr = new FileReader(file); 62 BufferedReader br = new BufferedReader(fr); 63 StringBuilder sb = new StringBuilder(); 64 String tmp; 65 while ((tmp = br.readLine()) != null) { 66 sb.append(tmp + "\n"); 67 } 68 textPane.setText(sb.toString()); 69 Runnable moveScrollBar = new Runnable() { 70 71 @Override 72 public void run() { 73 // TODO 自動生成されたメソッド・スタブ 74 scrollPane.getVerticalScrollBar().setValue(0); 75 } 76 }; 77 SwingUtilities.invokeLater(moveScrollBar); 78 br.close(); 79 } catch (IOException e1) { 80 // TODO 自動生成された catch ブロック 81 e1.printStackTrace(); 82 83 } 84 85 } 86 } 87 88 if (e.getSource() == newItem) { 89 if (file != null) { 90 file = null; 91 textPane.setText(""); 92 } 93 } 94 95 if (e.getSource() == saveBtn) { 96 if (!(file == null)) { 97 98 try { 99 FileWriter rw = new FileWriter(file); 100 BufferedWriter bw = new BufferedWriter(rw); 101 String tmp = textPane.getText(); 102 bw.write(tmp); 103 bw.close(); 104 } catch (IOException e1) { 105 // TODO 自動生成された catch ブロック 106 e1.printStackTrace(); 107 } 108 } else if (file == null) { 109 int selected; 110 selected = fileChooser.showSaveDialog(this); 111 if (selected == JFileChooser.APPROVE_OPTION) { 112 file = fileChooser.getSelectedFile(); 113 try { 114 FileWriter rw = new FileWriter(file); 115 BufferedWriter bw = new BufferedWriter(rw); 116 String tmp = textPane.getText(); 117 bw.write(tmp); 118 bw.close(); 119 } catch (IOException e1) { 120 // TODO 自動生成された catch ブロック 121 e1.printStackTrace(); 122 } 123 } 124 } 125 } 126 if (e.getSource() == clearBtn) { 127 textPane.setText(""); 128 } 129 } 130 131} 132 133class TextFilter extends FileFilter { 134 135 @Override 136 public boolean accept(File f) { 137 // TODO 自動生成されたメソッド・スタブ 138 if (f.isDirectory()) { 139 return true; 140 } 141 String ext = getExtension(f); 142 if (ext != null) { 143 if (ext.equals("txt")) { 144 return true; 145 } 146 } 147 return false; 148 } 149 150 @Override 151 public String getDescription() { 152 // TODO 自動生成されたメソッド・スタブ 153 return "textFile"; 154 } 155 156 private String getExtension(File f) { 157 String ext = null; 158 String fileName = f.getName(); 159 int dotIndex = fileName.lastIndexOf("."); 160 if ((dotIndex > 0) && (dotIndex < fileName.length())) { 161 ext = fileName.substring(dotIndex + 1).toLowerCase(); 162 } 163 return ext; 164 } 165}

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

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

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

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

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

y_waiwai

2023/08/26 23:34

このままではコードが読みづらいので、質問を編集し、</>(コードの挿入)ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
hoshi-takanori

2023/08/27 01:57 編集

setText の際にキャレットがテキスト末尾に移動して、その後の画面更新の際にキャレット位置にスクロールするからでしょう。setText 後に setCaretPosition(0) するとか?
Mitika-t

2023/08/27 04:30

コードの編集をしました。ご指摘ありがとうございます。 textPane.setCaretPosition(0)に変更したところ、swingUtilities.invokeLater();を 使わずとも実装できました。 getVerticalScrollBar().setValue(0); で値をセットした後でtextPaneのキャレット位置までスクロール しているということでしょうか?
guest

回答1

0

ベストアンサー

Swing はシングルスレッドで動作することはご理解されていると思います。そして Swing のコンポーネントの表示・更新は Swing のスレッド(EDT)の動くタイミングで行われます。

setText は「この文字列を自身に設定して表示しろ」という指示ですが、文字列を自身に設定するのは即行われても、表示は EDT 次第です。
表示が収まり切れない場合の表示位置(=スクロール位置)は、テキストのカーソルの位置が基本です。 setText はその文字列の最後の位置にカーソルを移動させますので、何もしなければ表示時にカーソルのある最後の位置が表示されることになります。
一方、スクロールバーの setValue も、「指定した値を"スクロール位置"として自身に設定して表示しろ」という指示で、スクロール位置の設定は即行われても、表示は EDT 次第です。

では、 setText による表示(とカーソルの移動およびカーソルの移動によるスクロール)と setValue による表示(スクロール)は何方がどのように動くのでしょうか。
setText も setValue も EDT に対する指示としては「表示しろ」だけで、 EDT は setText と setValue が行われた順番は知りません。従って、動作結果から見れば、 setValue によるスクロールの後に setText によるスクロールが行われていると推測出来ます。

invokeLater は EDT に対して「現時点までの要求が全て終わったらこの処理を行え」というものですので、 (setText の後に invokeLater を行っていれば)スクロールを含む setText の処理が全て終わってから setValue が行われたので動作したのでしょう。

投稿2023/08/27 04:57

編集2023/08/27 05:02
jimbe

総合スコア12648

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

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

Mitika-t

2023/08/27 06:23

理解できました。とても、親切な回答をありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問