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

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

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

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

Q&A

3回答

2906閲覧

Java.awt.Containerで、IndexOutOfBoundsExceptionが発生する原因とは

taka_miyata

総合スコア18

Java

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

0グッド

1クリップ

投稿2016/02/22 04:55

編集2016/02/24 06:12

JProgressBar で、以下の例外が、たまに発生します。

ダイアログに、JProgressBarをのせ、
処理進捗状況をスレッドで表示させています。

ダイアログを表示した際に、発生します。
何が、原因でしょうか。
また、回避する方法はありますか。
javaは、1.6です。

以下実装ソースです。実際、とても長いので省略します。

UserClass : 印刷処理を利用するクラス
PrintClass : 印刷処理を行うクラス
ProgDlgClass:進捗管理ダイアログクラス

java

1/** 印刷処理を利用するクラス */ 2class UserClass extend JFrame { 3 /** 印刷処理 */ 4 private void PrintProc ( ){ 5 PrintClass printCl = new PrintClass(); 6 printCl.executePrint( this ); 7 } 8 9} 10/** 印刷処理を行うクラス */ 11class PrintClass { 12 13 JFrame frame; 14 ProgDlgClass dialog; 15 /** 印刷処理 */ 16 public void executePrint( JFrame frame ) { 17 18 dialog = new ProgDlgClass( frame, false );// モーダル false 19 20 dialog.setProgressMaximum( 0 ); 21 dialog.setProgressMaximum( 0 ); 22 dialog.setProgressValue( dialog.getProgressMinimum() );//最小値をセット 23 dialog.setProgressAuto( true ); // 最初は不確定モード 24 25 // 進捗表示のスレッド 26 Thread thread = new Thread( new Runnable() { 27 @Override 28 public void run() { 29 try { 30 dialog.execute(); 31 } 32 catch ( Exception e ) { 33 //ここで例外ログ表示 34 } 35 } ); 36 thread.start(); 37 displayWaiting(); 38 39 // 印刷処理実行スレッド 40 Thread thread2 = new Thread( new Runnable() { 41 public void run() { 42 executePrint(); 43 } 44 } ); 45 thread2.start(); 46 47 } 48 49 /** 進捗画面の表示待ち */ 50 private void displayWaiting() throws Exception { 51 for ( short i = 0; i < 300; i++ ) { 52 if ( dialog != null && dialog.isVisible() ) { 53 Thread.sleep( 100 ); 54 return; 55 } 56 Thread.sleep( 10 ); 57 } 58 } 59 /** 印刷データ作成 */ 60 private void executePrint() { 61 for( int i = 0 ; i < ・・・ ) { 62 dialog.setProgressValue( i ); 63 //印刷データ作成 こちらで、プログレスバーの値を設定し、進捗状況を管理 64 } 65 } 66 67} 68 69/** 進捗管理 */ 70public class ProgDlgClass extends JDaialg { 71 72 private JProgressBar jProgressBar1 = new JProgressBar(); 73 private int progressMinimum; 74 private int progressMaximum; 75 private JPanel = panel1 = new JPanel (); 76 77 /** コンストラクタ*/ 78 public ProgDlgClass( Frame owner, boolean modal ) { 79 super( owner, modal ); 80 jProgressBar1.setStringPainted(true); 81 panel1 .add(jProgressBar1); 82 jProgressBar1.setBounds(10, 10, 220, 30); 83 this.getContentPane().add(panel1 , java.awt.BorderLayout.CENTER); 84 this.setPreferredSize( new Dimension( 245, 140 ) ); 85 } 86 87 /** 88 * 開始 89 */ 90 public void execute() throws Exception { 91 if ( this.progressMaximum == 0 && 92 this.progressMinimum == 0 && 93 this.progressAuto == false ) { 94 // ここは、progressAuto = trueのため、今回は通らない 95 return; 96 } 97 this.setVisible( true ); 98 } 99 100 /**プログレスバーの最大値設定 */ 101 public void setProgressMaximum( int wkValue ) { 102 this.progressMaximum = wkValue; 103 this.jProgressBar1.setMaximum( wkValue ); 104 } 105 106 /** プログレスバーの最小値設定*/ 107 public void setProgressMinimum( int wkValue ) { 108 this.progressMinimum = wkValue; 109 this.jProgressBar1.setMinimum( wkValue ); 110 } 111 112 /** プログレスバーの最小値設定*/ 113 public int getProgressMinimum() { 114 return this.progressMinimum = wkValue; 115 } 116 117 /** プログレスバーの最小値設定*/ 118 public int getProgressMinimum() { 119 return this.progressMinimum = wkValue; 120 } 121 122 /** プログレスバーの現在値を設定 123 * @param wkValue 設定しようとするプログレスバーの現在値 124 */ 125 public void setProgressValue( int wkValue ) { 126 this.jProgressBar1.setValue( wkValue ); 127 } 128 129 /** プログレスバーの自動処理状態を設定します。 130 * @param wkBool 自動処理状態 true:勝手に動作します。 131 */ 132 public void setProgressAuto( boolean wkBool ) { 133 this.progressAuto = wkBool; 134 this.jProgressBar1.setIndeterminate( this.progressAuto ); 135 this.jProgressBar1.setStringPainted( !this.progressAuto ); 136 } 137}

PrintClass の executePrintがexecuteされ、ProgDlgClass が表示された時に例外が発生。
終了は別途ボタンが有り、ボタン押下でdispose()が実行されます。

以下 例外内容
java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at java.awt.Container.createHierarchyEvents(Container.java:1357)
at java.awt.Container.createHierarchyEvents(Container.java:1357)
at java.awt.Container.createHierarchyEvents(Container.java:1357)
at java.awt.Container.createHierarchyEvents(Container.java:1357)
at java.awt.Container.createHierarchyEvents(Container.java:1357)
at java.awt.Dialog.conditionalShow(Dialog.java:939)
at java.awt.Dialog.show(Dialog.java:1040)
at java.awt.Component.show(Component.java:1516)
at java.awt.Component.setVisible(Component.java:1468)
at java.awt.Window.setVisible(Window.java:841)
at java.awt.Dialog.setVisible(Dialog.java:991)

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

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

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

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

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

guest

回答3

0

直接的な解決策ではありません。
問題の原因は、すでに皆様からご指摘があった点と思われます。

わたしは、プログレスバー・進捗状況をUIとして伝える場合、スレッド側(なんらかの処理を行う側)が能動的に行うのではなく、UI側がタイマー等で定期的に処理の進捗状況を取得してUIに反映させることが問題を最小化する方法と考えております。

スレッドで処理を行う側は、処理を行いつつ、進捗状況をある変数に設定する。
UI側は、定期的に上記変数を参照しプログレスに反映させる。

一般的にUIに関わる操作をUIスレッドとは別のスレッドで操作する際に問題が起きやすいなどもあり、また、処理側で能動的にプログレスを動かしても人間の目で追いつけるほどの進み方をするのかも処理に依存する、さらに処理スレッドの終了処理のタイミング制御が難しくなり、無効領域を参照してしまうなど副作用が大きくなるからです。

投稿2016/02/24 04:44

t_obara

総合スコア5488

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

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

0

何かしらのリストの操作、特に削除をメインのスレッドで行って、同時にこっちの「処理中」のスレッドで参照している、とかでしょうか。
処理中スレッドでインデックスをインクリメントして、このときはまだリストのサイズ内のためループに入るけど、メインのスレッドでリストから要素を削除したためサイズが変わり、参照出来なくなった、という可能性位しか思い付きません…

投稿2016/02/22 08:01

swordone

総合スコア20651

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

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

taka_miyata

2016/02/22 12:51

スレッド生成でイベントが処理されて、イベントの管理から 抜かれているのでしょうか。 その場合、スレッドセーフにすることが可能なのでしょうか。
guest

0

原因は、IndexOutOfBoundsExceptionだと思いますが
心あたりはありませんか?

dialogの中でListを扱ってる処理はなんでしょうか?

その配列の要素外にアクセスしたのではないでしょうか?

投稿2016/02/22 07:08

hato_pato

総合スコア215

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

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

taka_miyata

2016/02/22 12:49

java.awt.Container.createHierarchyEvents でイベントを生成しているような感じですが、 ここで配列の数があわなくなる原因を知りたいと思っております。 イベントは、実装側で詰めることが無いと思っているのですが・・・
taka_miyata

2016/02/24 00:29

ありがとうございます。 言われる通り、ダイアログには、JprogressBarがあり、 スレッド生成元が、このJprogressBarに、値を設定しています。 最初は、スレッド生成元側からJprogressBarに値を設定している方法が おかしいと思って調査していましたが、例外が発生しだすとダイアログに 設定する値が変わろうとも、例外発生が止まらない状態となります。 その時は、jarファイルを再構築(ソース変更は無し)したりして、 現在、対応しています。 紹介して頂いたサイトとやっていることは、だいたい同じと思っていますが・・・ ダイアログは、モーダレスで、浮かべています。 スレッド生成元の処理が終わったタイミングで、ダイアログに対して、 dispose()を行っています。
hato_pato

2016/02/24 01:00

例外発生が止まらない状態の 発生している例外について情報共有していただけますか?
taka_miyata

2016/02/24 04:32

申し訳ありません。 例外発生が止まらない状態というのは、 あるタイミングより、このスレッドを動作させ、ダイアログを setVisible( true )にした瞬間に、必ず、発生すると言うことです。 サンプルソースでいうと、dialog.execute()の部分になります。 連続して、絶えず例外が出てくるイメージを作ってしまい申し訳ありません。 execute()メソッドは、独自の実装となりますが、 progressBarに与える変数の初期化と、ダイアログのsetVisible( true )を 行っているのみです。 setVisibleで例外は発生しているようで、上記の例外のトレースが、 出力されています。 ダイアログの実装クラスです。execute で行っていることの抜粋。 public class WorkDialog extends JDialog{ public void execute() throws Exception { // 変数初期化処理 // ↓ ダイアログの表示 this.setVisible( true ); } }
hato_pato

2016/02/24 04:57

JprogressBarの実装はどうしてるんですか? 小出しでも良いですが、問題の箇所が明らかになった方が 回答しやすいです。 実際にご自身でコーディングしたソースを見せて頂けますか?
taka_miyata

2016/02/24 06:03

すべてのコードが書けないので、該当箇所と思しき所の コードを質問に 追加させて頂きました。 実コードは、個人の所有物で無いので、公開できず、申し訳ありません。 不足があれば、教えて下さい。 公開できる範囲で、提供させて頂きます。
hato_pato

2016/02/24 07:33

切り分けのため、dialog.execute();をThreadの外で実行することは可能ですか?
hato_pato

2016/02/24 07:36

印刷処理だけ別スレッドで実施すれば良さそうな気がしますが、 違いますかね?
taka_miyata

2016/03/03 00:14

回答が遅くなり、申し訳無いです。 1.Threadの外に出す案 ダイアログは、表示中は、裏で動作しているフォームは、制御不能にするため、 モーダル状態にしています。 モーダル状態では、ダイアログを閉じるまで、制御が戻って来ないので、 後続処理を行う為、スレッドにしています。 その為、Threadの外に出せない状態です。 2.印刷処理だけ、別スレッドで実施 別スレッドに出すと言われるいる内容が、ちょっと具体的にどのようにすれば、 良いのか。分からない状態です。 印刷処理を呼び出すモジュールは、サンプルのPrintClassを呼び出すだけで、 進捗バーのダイアログを出しながら、その裏で、印刷処理を行いたいです。 進捗バーのダイアログを出している間は、呼び出したモジュールの制御は 制限したいです。 この要件を満たす為に、あのようなサンプルソースとなっています。 逆の発想で、印刷処理のスレッドを先に起こし、その後、モーダルで 進捗のダイアログをスレッド外で表示したところで、今回の例外の根本理由が 分からないと、ちょっと解決にならない感じと思われますが、いかがでしょうか。
hato_pato

2016/03/03 02:19

ダイアログのコンストラクタ内で、 super()の後ろで getModalityTypeを取得してもらえますか? モーダルのタイプの影響は考えられないでしょうか?
taka_miyata

2016/03/03 04:29

アドバイスありがとうございます。 ModalityType は、 DOCUMENT_MODAL が取得出来ました。 ModalityTypeの事がよく分からないのですが、 何か、重要な問題がありますでしょうか。
hato_pato

2016/03/03 05:04

hierachyeventsの意味が分からなかったので調べてみたのですが Windowとかダイアログの階層(重なり)のようだと思いました。 モーダルで表示する際のタイプが以下4タイプに分かれているようで modalityTypeを変更したらエラーが変わるか試して頂きたいと思いました。 (https://docs.oracle.com/javase/tutorial/uiswing/misc/modality.html) APPLICATION_MODAL DOCUMENT_MODAL TOOLKIT_MODAL MODELESS 現在、DOCUMENT_MODALなので APPLICATION_MODAL または TOOLKIT_MODAL をsetModalityTypeでセットしてみたらどうなりますか?
taka_miyata

2016/03/03 10:53

ありがとうございます。 試してみましたが、今、開発しているアプリでは、 メニューから複数のアプリを動作させています。 これらのmodalityTypeの設定を行うと、ダイアログが出ている間は メニュー自体の制御まで制限されてしまいました。 その為、今まで提供していた複数の機能を同時に動かすことが 出来ないことが判明し、DOCUMENT_MODALしか やりたい事が 出来ない状況でした。 申し訳ありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問