X



トップページ独身男性
660コメント436KB
System.out.println("またJavaの季節がやってきた!" + 2);
■ このスレッドは過去ログ倉庫に格納されています
0001おれさま ◆6CTEZS59O00a
垢版 |
2018/09/13(木) 10:42:14.49
去年の今頃Java学習開始するも挫折
しかし不屈の闘志をめらめらと燃やしながら
そびえ立つ岩壁にいどむため、再びこの地にやってきたのだ!

プログラミング歴は独学Cチョビッツ+独学VBA少々


きょうかしょ
https://www.amazon.co.jp/dp/484433638X
スッキリわかるJava入門 第2版 (スッキリシリーズ)
0002Mr.名無しさん
垢版 |
2018/09/13(木) 10:42:29.06
Swingをいれてみた
JavaFXはいろいろエラー吐いてうまく行かないというか原因がよくわからんから
SwingをGUIの部品として採用
Swingのいいテキストあったら買いたかったけど古いのしかないからネットで知識漁ることにした
最初はシンプルな作りで十分だし

https://www.javadrive.jp/tutorial/
ここみながらぼちぼちやっていく
0004おれさま ◆6CTEZS59O00a
垢版 |
2018/09/13(木) 11:40:09.85
windowsbuilderとかscenebuilderとか使ってウィンドウ作って行くとダメだな
あれは理解出来てる人が使うものだ
0011Mr.名無しさん
垢版 |
2018/09/15(土) 09:04:17.52
いやっほおおおおおおお週末だぜいぃ!
JavaJavaすっかね
0012おれさま ◆6CTEZS59O00a
垢版 |
2018/09/15(土) 09:21:27.49
ごく基本的な構造そなえたウィンドウを形成するコードは暗記することにする
何度も繰り返し書くのである
0013Mr.名無しさん
垢版 |
2018/09/15(土) 14:03:30.15
ActionListener関係はちょっと複雑であり
しかも重要性高いので慎重にいくのであります

原理をちゃんと理解するのである
0015おれさま ◆6CTEZS59O00a
垢版 |
2018/09/15(土) 15:15:50.52
多重継承がここででてくるんだよな
いろいろ基本の復習勉強できていいかもしれない

ちなみに継承なのか承継なのかいつも迷う
承継は小計みたいだからだめ!と覚えよう
0018おれさま ◆6CTEZS59O00a
垢版 |
2018/09/15(土) 15:21:50.64
GUIの基本であるこの辺でみられる技は見事だな
extendしたJFrameのメソッドをコンストラクタで使うあたりとか
プロの技って感じです
こういう風に使うんだなぁと
0019おれさま ◆6CTEZS59O00a
垢版 |
2018/09/15(土) 15:24:56.13
public void actionPerformed(ActionEvent e) {
System.out.println("腹減ったしメシくうか");
}
0020おれさま ◆6CTEZS59O00a
垢版 |
2018/09/15(土) 16:17:07.63
GUI分野の部品はこれで大体完成
次は定期処理の部品を学んでいく予定

ざっとみたところ学習する内容は
TimerTask
Timer
ScheduleExecutorService
0021おれさま ◆6CTEZS59O00a
垢版 |
2018/09/15(土) 16:21:40.66
あと、前から気づいていたんだけど、クラスを今までに学んだことのない方法で使ってるのをみかける
どうやらこれを無名クラスとか匿名クラスとか呼ぶようだ
わかりにくいから普通の使い方に書き換えて今まで使ってたんだけど
頻繁にでくてくるのでちゃんと頭に入れた方がよさそうな気もする
0023おれさま ◆6CTEZS59O00a
垢版 |
2018/09/16(日) 05:03:22.53
定時処理難しいな
windowsのタスクスケジューラに任せることにしよう
とするとGUI使わないほうがよさそうだな
まぁ今の段階ではそれでいいか
0024おれさま ◆6CTEZS59O00a
垢版 |
2018/09/16(日) 05:24:18.81
GUIアプリで
開始ボタンを押すことで毎日定時に処理するようにする
停止ボタンを押すことで定時処理を停止させる

をやろうとしたんだけど、いろいろとまだ知識足りない
threadとかの知識も必要なんだけど実践編でもあまり書いてなさそう

thread
interrupt

とか使うといけそうなんだけど、いろいろと問題も起きそうで
それを回避するための仕組みがイマイチ難しい
0025おれさま ◆6CTEZS59O00a
垢版 |
2018/09/16(日) 06:31:50.45
おれの作った最初のソフトウェアでけたああああ
ショボイけど

グローバルIPアドレスを記録していくプログラム

実行すると、実行ファイルと同じフォルダにテキストファイルを作成し
グローバルIPアドレスを日時とセットでかき込む
(ついでにプライベートIPアドレスもセットでかき込む)
実行するたびに同じファイルに追記していく
年ごとにファイルを新しく作っていく
タイマーは難しかったんでwindowsのタスクスケジューラで毎日定時に実行することにした

おれの環境は時々IPアドレスが変わるんで
いつ変ったのか知りたくて自動で記録していくフリーソフトないかなと探してたんだけど
よさそうなのがなかった
単純な動きなので自分で作れたらなぁと思ってた
0026おれさま ◆6CTEZS59O00a
垢版 |
2018/09/16(日) 06:52:59.02
問題はタスクスケジューラが正常に動いているかだ
壊れちゃってたのが治ってなければ意味なし
0027おれさま ◆6CTEZS59O00a
垢版 |
2018/09/16(日) 06:57:46.00
どうやらタスクスケジューラでjar実行ファイルを起動するときは
javaw -jar C:\〜パス〜\test.jar
みたいにしないといけないみたいだ
exe化してもいいんだけどどうしようかな
0028おれさま ◆6CTEZS59O00a
垢版 |
2018/09/16(日) 08:38:25.45
うーむ
不思議なことにexe化してもしなくてもタスクスケジューラから起動すると挙動がおかしい
一瞬コマンドプロンプトが表示されて、
System.out.prinlnで指定した文字列が見えるからプログラムの一部は動いている感じはする
でもテキストファイルを作ってくれない

ためしにバッチファイルをかましてみようと思い作成、
ひとまず手動でバッチファイルを起動してみたらバッチファイルが消滅
おいおいアバストさん・・・・

もしやおれのプログラムもまさかこいつが・・・
と思ったがどうやら違う
アバストを停止させてもテキストファイルを作ってくれない

バッチファイル噛ませばいけるならそれでいいか
0029Mr.名無しさん
垢版 |
2018/09/16(日) 12:25:29.72
1個しょぼいの作ったらPythonに目移りしてきた
どどどどどどどどどどどしようかすら
0030Mr.名無しさん
垢版 |
2018/09/16(日) 12:52:03.01
GUIを作りたいんだよな
そうするとWPFとかいうのがヒットする
C#なのか
そうなのかそうなのか
どどどどどどどどどどどどどどどしようかすら
0031おれさま ◆6CTEZS59O00a
垢版 |
2018/09/16(日) 12:54:51.38
てかもう1個Javaでしょぼいのつくろうかな
今欲しいプログラム思いついた
0032Mr.名無しさん
垢版 |
2018/09/17(月) 16:17:28.90
時計作った
USA東部時間をサマータイム込みで知りたいこと多いから常時表示させるやつ

いろいろと問題にぶち当たったけど、一応役に立つものができあがったんでOK

あと、アマゾンでプログラミング関連の本注文しまくってしまった
C#
python
javascript

一応しばらくはJava中心だけど気が向いたらほかのもやろう
すっきりの実践編を読み終えたいな
入門編も完全に自分のものにしたとも言えないし
0034おれさま ◆6CTEZS59O00a
垢版 |
2018/09/19(水) 18:17:12.26
HTML・CSS・Javascript関連の初心者本に浮気してる
HTMLはずいぶん昔に多少勉強したことあるんだけど、
当時はいかに見せるかに力点がおかれてたと思う
今は最初から入力欄やボタンやらを紹介するのな
利用してもらうってのが先にある
ずいぶん変ったもんだ
0035おれさま ◆6CTEZS59O00a
垢版 |
2018/09/20(木) 14:35:13.38
作った時計プログラムのタイトル消して
ウィンドウごとDDして移動させたり、右クリックメニュー付けて終了できるようにしたりしてるんだけど
なんだかググって適当にコピペしてるだけでなんとなくできてしまうのはいいんだろうか・・・

イマイチ理解できてない部分もあるんで後々ちゃんとやっていこうと思ってはいるんだけど

大体欲しかった機能付けられた
前回閉じた場所で開く機能をつけたらほぼ完成だな
0036おれさま ◆6CTEZS59O00a
垢版 |
2018/09/22(土) 04:29:28.68
機能追加のために足りない知識を補う目的で部分的に実践編読んでるんだけど
やっぱネットと違って説明がしっかりしてていいわぁ
ちゃんと読む価値あるなといまさらながら思った
最低限実践編までは読まないと、無駄に時間食う
0037おれさま ◆6CTEZS59O00a
垢版 |
2018/09/22(土) 06:21:38.35
前回閉じた場所で開く機能も付けた
iniファイルを作って座標を保存しておくタイプにしたんだけど
ファイルが消えちゃったとか中身がおかしくなっちゃったときとか
いろんなトラブルに対処できるようにするとなかなか難しい
ある程度対処できたけど、まだ完全じゃない
0041おれさま ◆6CTEZS59O00a
垢版 |
2018/09/23(日) 17:37:04.06
単純にテキスト流して読んで問題といて頭に入っていくかというとそうでもない

そこで、
簡単な機能ではあるけど、自分が必要だと思うコードがふんだんに含まれる
プログラムを用意してこれを何度も書いて覚えることにする
学習の骨格がないと肉付けする過程でぐらぐらゆれちゃってなかなか覚えられないんで
骨格部分をちょっと頑張って頭にいれよう
0042おれさま ◆6CTEZS59O00a
垢版 |
2018/09/26(水) 12:35:48.85
ウィンドウ操作とかいろいろできるようになってきた
おもろいなぁ
APIレファランスだっけ、だんだん読めるようになってきた
もう一度すっきり入門編の後半読み直したいな
あの辺大事だわ
0043おれさま ◆6CTEZS59O00a
垢版 |
2018/09/26(水) 14:23:00.29
ヤフーの天気予報を表示するようなwindowsアプリってどういう風にサーバから情報を得てるんだろうと思ったんだけど、
ヤフーがそのためのAPIを提供してるんだな
おそらくアプリ作った人が自分が運用してるサーバで情報取得する
配布した個別のアプリはそのひとのサーバに接続して情報取得する
こんな感じなのかな
ヤフーに直接接続するとなるとアプリケーションIDとやらが必要となるそうなので現実的ではないんで、こういう感じで間接的に情報取得してそうだ
もし自分だけで利用するアプリつくるなら、ID登録後に直接ヤフーから情報取得すればよさそう
0045おれさま ◆6CTEZS59O00a
垢版 |
2018/09/28(金) 11:52:36.88
天気予報を常時表示してくれるソフトは昔から使っているんだけど
そのソフトの情報取得先のヤフーが提供するデータに明日の天気がないらしい
そのため明日の天気が表示されない

そこで、明日の天気だけを表示するちっこいソフトをつくろうかと思う
APIを使うとたぶん同じことになるんでHTMLから適当に抽出してやろうと計画してる
しかしだ、頻繁にHTMLを変えられてしまうとなかなか難しいかもしれない
0046おれさま ◆6CTEZS59O00a
垢版 |
2018/09/28(金) 14:08:41.84
http と https ではHTMLの取得方法を変えないといけないのか
文字化けするから文字コードがらみでいろいろ調べてたんだが違っていた

URLクラスではなく
URLConnectionクラスを使ったらHTML取得までうまくいった
0047おれさま ◆6CTEZS59O00a
垢版 |
2018/09/28(金) 14:22:15.84
いや、ちがうな・・・
URLクラスでいける
この辺はいつか解決する課題として残そう

char型使って読み込んでいく最も入門的なコードだと、どこかで文字がおかしくなる
StringBuilderが原因かと思ったがそうでもなさそうだ
0048おれさま ◆6CTEZS59O00a
垢版 |
2018/09/28(金) 15:50:56.60
ふぅ・・・ひとつひとつ壁があるわい
お天気マークのgifをそのままフレームに表示させようと思ったがなぜかできない
ローカルにある画像ファイルならいける
いろいろ調べたらようやくわかった
URLクラスのインスタンス使わないとだめなようだ
つまり
ImageIcon ii = new ImageIcon("./img/aa.jpg")
はおkだけど
ImageIcon ii = new ImageIcon("http://www.eee.jp/ee/aa.jpg";);
はダメ
ローカルにない画像使いたい時は、一旦
URL url = new URL("http://www.eee.jp/ee/aa.jpg";);
として
ImageIcon ii = new ImageIcon(url);
とするのが正解
0049Mr.名無しさん
垢版 |
2018/09/28(金) 21:36:43.11
おれさま!がんばってるな!見ているからこれからも頑張って
0051おれさま ◆6CTEZS59O00a
垢版 |
2018/09/29(土) 12:41:59.91
https://dotup.org/uploda/dotup.org1654406.jpg
まだ途中だけど、こんな感じでいく
アイコンはヤフー天気からそのまま借用
データは全部普通にヤフー天気開いた時に取得するHTMLから
必要な部分切り出して利用した
ヤフーがURLやらHTMLの中身を変えちゃうと表示できなくなる
でも自分で作って自分でしか利用しないからこれで十分だ

あと付け足さないといけない機能は
数時間おきにデータとりに行く機能と右クリメニューから閉じる機能
あと、前回閉じた場所で開く機能

どの機能もいままで作った2つのプログラムから借用できるので大した事はない
0052おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 08:09:39.53
機能完備して完成



なんだけど、さっきググってたら面白そうなの見つけた
おれのお天気表示プログラムはヤフー天気のHTMLを取得して特定ルールのもとで
splitを使って分割、配列に格納してる
この特定ルールなんだけど、できたらタグを目印にぶつぶつと小間切れにしていく方向でやりたかった
しかしだ、正規表現<.*>を使って表現したタグでsplitすると
たとえば、このHTML

<div>ちんちん</div>
<p>まんまん</p>

を配列に格納すると
要素番号0 ちんちん</div><p>まんまん
要素番号1 (なし)

となってしまう
本来は

要素番号0 ちんちん
要素番号1 まんまん

とならなければならない

どうやら * は「よくばり」らしくて、途中で > が表われてももっと後ろに > があれば
まだまだいけるだろーとどんどん先へ進んで行ってしまうようだ
それが分かったあと、まぁ正確にタグで区切る必要も無いだろうと考えて
< 記号でsplitしてたんだけど・・・・・
0053おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 08:15:37.26
<.*?>

という書き方があるそうだ
これでやると

要素番号0 ちんちん
要素番号1 まんまん

が実現できるそうだ
この ? 記号は普通の ? 記号(直前パターンの0回か1回の繰り返し)ではなく
* の「よくばり」を消し去る効果をもつらしい
つまり、タグの中を * が進んで行く途中で、 > が現れた瞬間にそれ以上進むのを諦めてくれるそうだ

これを「最短一致」という
デフォルトは「最長一致」なのだが、最長もこれはこれで使えそうだ
最短一致は正確には→の方向に進んでいく場合の最短一致で
逆方向には働かないので注意
0054おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 08:17:47.37
>>52を修正
要素番号0 ちんちん</div><p>まんまん
要素番号1 (なし)

↑間違い 正確には↓

要素番号0 div>ちんちん</div> (改行記号が入る) <p>まんまん</div
要素番号1 (なし)
0056おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 08:24:33.56
おれが今使わせてもらってる誰かが作ったお天気表示ソフトなんだけど
iniファイルをみたら、おれが利用してるヤフー天気のHTMLと同じURLが書いてあった
とすると、このソフトはおれと同じようにHTMLを加工して作っているのでは・・・

もしそうならヤフーがHTMLを改変し、おれのお天気表示ソフトが正確に表示されなくなったタイミングで
このソフトも同じ症状を見せるんではないかと思う
もちろんHTMLの分析の仕方いかんで、そうとも言い切れないだろうけど、観察してみる価値ありだ
0057おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 08:27:04.70
ちなみにだけど、
<.*?> でタグを表現する方法は不完全らしい
しかし、その不完全さを理解するにはもうちとHTMLやらweb系の知識がいるようなので後回しにしていこう
0058おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 08:28:56.47
>>54を修正
要素番号0 div>ちんちん</div> (改行記号が入る) <p>まんまん</p
要素番号1 (なし)
0059おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 08:32:14.87
そういや気温表示がなかった
これ付けておきたいな
特にこれからの季節寒いんで
0060おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 11:09:23.22
複数ラベルについてforやら使ってまとめてコード書こうとしたら大変な目にあった

ラベル名の一部に数字使ってこれを変数に置換えてforで回す方法はないかと模索したができないようだ
つまり
for (int i = 0; i < 5; i++) {
label_i.setText("おほほ");
}
みたいのはだめ

配列使う方法で代用できそうなので試してみたが、ここでまた問題勃発

JLabel[] lbl = new JLabel[5];
for (JLabel bb : lbl) {
bb.setText("むほほ");
}

これでだめときた
あの有名な ぬるぽ が出てしまう
ぐぐりまくってようやくわかったのが
このコードではJLabelのインスタンス化が済んでいないということ。
配列の作り方とインスタンス化が結構似てるんで両方が組み合わさると混同してしまうのがポイント
正解は

JLabel[] lbl = new JLabel[5]; //←ここでは配列変数と配列の実体が作られただけ
for (JLabel bb : lbl) {
bb = new JLabel(); //←JLabelのインスタンス化のためこの1行が必要!
bb.setText("むほほ");
}


さらにforの中でswitchを使ったのだが
案の定break;を忘れて、忘れたことに気づかずに試行錯誤1時間ですわ
0061おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 12:18:48.20
main factory already defined

exewrapを使って作ったexe実行時にこのエラーが出るのは
実行可能jarファイルをエクスポートするときライブラリー処理を
上から2番目の選択肢にするから。
一番下を選択すること

隣のサブフォルダにコピーするとかなんたらこうたらのを選択
0063おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 13:30:49.27
祝日自体そう多いわけでもないから
内閣府が出してる振替休日込み祝日等のcsvをそのまま使うっていう手もあるな




ん〜
そういえば定期的な実行にthreadとsleep使ってたんだけど
これはあまり良くないとかいうのを読んだ
もう少し基礎力アップさせてから次のソフトに挑んだ方が良いのかもしれない
今のままでもいろいろ作れることは分かったけど、もう少し基礎知識の幅の広さが欲しい
0064おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 16:02:53.01
Swingを使ったWindowsアプリを作っていると
継承の知識をちゃんと生かしていかないと理解できなくなる
右クリックメニューの項目を作るためのメソッドがあるんだけど、
これにActionListenerクラス型変数「のようなもの」を引き渡さないといけなかったりする

「ようなもの」というのは、そもそもActionListenerはインターフェースでインスタンス化できない
今の知識ではこれをなんと呼ぶのかよく分からない

ここで、引き渡す際の実引数にthisを使うとなぜかうまくいく
適当にやったらうまくいったのだが、自分でやっていて頭が混乱してしまう

落ち着いて考えてみたら理解できた

つまり、まず、
クラスの宣言でこうやってる
public class Main extends JFrame implements ActionListener

そしてmainメソッドで
Main mm = new Main();
のようにインスタンスを生成している

ここでthisとは何を指すのかと言えば
Main型変数mmということになる
このmm、実はActionListener型変数(のようなもの)でもある
なぜかというとMainクラスはActionListenerを実装しているからだ

だからthisでうまくいくのだ・・・・(と今のところ思っておこう
0065おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 16:13:25.61
インターフェースはインスタンス化できないだけで
インターフェースの変数は作れるということかな
ActionListener al
みたいのはそういうもんか


あと、
インターフェースのインスタンス化に絡んで分からなくなるのが匿名クラス

JButton btn = new JButton();
btn.addActionListener(
 new ActionListener() {
  public void actionPerformed(ActionEvent e) {

  }
 }
);
みたいなやつ
これもActionListenerをnewしてるからおかしいじゃん!って思うんだけど
ぐぐってみたら、これは、みためはインターフェースActionListenerをnewしてるようで
実はActionListenerを継承した匿名クラスをnewしてるんだそうだ
0066おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 16:23:42.24
すっきり入門を読んでいる段階では、
オブジェクト指向というものはわかりやすくメンテしやすいコードを書くための技法であって
一歩先へ進みたいなら理解しておいたほうがいいよって程度に思えたんだけど

実際windowsアプリ作り始めると、基本的なコードを理解するのに必須な知識だと分かる
理解できてないと話にならないというレベル

まぁまだ理解仕切れてないし忘れちゃってる部分もあるんで読みなおそっと
0067おれさま ◆6CTEZS59O00a
垢版 |
2018/09/30(日) 16:50:27.99
MainクラスにActionListenerを実装させない方法だと、

btn.addActionListener(new al());
として、これとは別に実際の処理を任せるクラスをつくる
public class al implements ActionListener {
 public void actionPerformed(ActionEvent e) {
 
 }
}
こういうのがどちらかというと基本のコードだから
>>65の匿名クラスのnewというのは、ここでいう al みたいのをnewしてるってことか
0068おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 11:34:06.14
jarのままだとタスクマネージャやらにファイル名が表示されないから
基本的にはexewrapを使ってexe化している
しかし何度もコマンドプロンプト開いてうだうだ繰り返しやってると煩わしいので
D&Dして処理するできるようバッチファイルを作った

@echo off
if %~x1 == .jar (
 exewrap -g %1
) else (
 echo .jarではありません。
)
pause

久々にバッチファイルについてぐぐってみたんだけど
意外といろいろ出来ちゃうんだということを思い出した
0069おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 12:00:56.09
パネルの上にもう一枚枠線だけで中身は透明のパネルをかぶせることで
すこしだけおしゃれにしてみた

この2枚重ねのパネル、簡単だと思ったのだが以外とつまずきが多かった

JPanel pnl_1 = new JPanel();
Jpanel pnl_2 = new JPanel();//こいつを透明化して枠線だけ設定することにする
pnl2.setOpaque(false);//透明化

Container contentPane = getContentPane();
contentPane.add(pnl_1);
contentPane.add(pnl_2);

でいけるだろ〜と思ったら大間違いだった
こんだけやったら思い通りになった↓もしかしたら不必要なものもあるのかもしれないが

・pnl_2はcontentPaneにaddするのではなく、pnl_1にaddする pnl_1.add(pnl_2);
・pnl_1はsetSize()でフレームと同じ大きさにサイズ設定 pnl_1.setSize(100, 100);
・pnl_2はsetBounds()で位置サイズ固定。
 ぴったりpnl_1にかぶせるのであれば pnl_2.setBounds(0, 0, 100, 100);
0070おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 12:05:53.56
たぶんLayoutにも関連してくるんだと思う
今のところだけど、

contentPaneは setLayout(new BorderLayout());
pnl_1は pnl_1.setLayout(null);

としてある
0071おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 13:07:09.74
フォントの種類っていろいろあるけど今までほとんど気にしたことなかった
デフォルトで表示される日本語フォントがあまりに変なのでメイリオっていうのに変更した
0072おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 14:19:25.74
すっきり入門読み直してるんだけど
windowsアプリ作ってる時になんどかstatic関連のエラーが出た
なんとなく適当にやったら切り抜けられたんだけど
ちゃんと頭に入れないといけない

いつも忘れるのは

「staticメソッドからはstaticではないメンバを呼び出せない」

ということ。
何度かこれでつまずいたんだけど、そのうちの一つがthread関連の処理をしたとき
threadはまだちゃんと理解できてなくて、それが原因というのもある
threadを使うだけの簡単なプログラムをつくれと言われたら簡単なんだけど
自分がそれまで書いたコードを前提にして、そこにthreadを組み込もうとするといろいろ制約が出てきて難しくなっていくのだ
0073おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 14:55:27.22
そもそもスレッドは鬼門なのだ
すっきりでも実践編の最後に触れているだけで
入門編しか読んでないおれが立ち入ってはいけない領域だったのだ
しかしスレッドを利用しないとなるとさらに難しいコードを書かなければならなさそうだったので
あえて踏み込まざるを得なかった

まず第一の制約がこれだった

メインに使うクラスをMainとした場合、このMainクラスはこう宣言されている
public class Main extends JFrame

普通スレッドを使う時は extends Thread を使うのだが
しかしextendsによる多重継承はゆるされないため、Runnableを使う事になる
public class Main extends JFrame implements Runnable
と宣言することになる

と書いたのだが、実は
ごく基本的なコードを書くのであればRunnableはメインのクラスに実装するものではない
それはあとになって分かったことなのだが、基本レベルではこう書く
もちろんSwingを使ってwindowsアプリをつくる前提で。

public class Main extends JFrame {
 public static void main(String[] args) {
  Main mm = new Main();
  Aa aa = new Aa();
  Thread thrd = new Thread(aa);
  thrd.start();
 }
}

public class Aa implements Runnable {
 public void run() {
  System.out.println("この辺に処理内容を書く");
 }
}

つまり、Mainとは別に処理系のクラスを作って、これにRunnableを実装するのだ
そしてmainスレッドでThreadクラスのインスタンスを生成するときに
処理系クラスのインスタンス変数を引数として渡すことになる
0074おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 15:10:03.70
しかし、おれが何もわからないまま参考にしたコードではメインのクラスはこう宣言されていたのだ
先ほど書いたものをもう一度書くが、これだ

public class Main extends JFrame implements Runnable

つまり、本来メインのクラスとは別にRunnableをimplementsするクラスをつくるはずが
そのクラスをメインのクラスに吸収するような形で合体させてしまっているのだ
その結果、メインのクラスにRunnableをimplementsさせてしまっているわけだ

これはextends JFrameと同じ構造だ
これも基本レベルではメインのクラスとは別のクラスを作ってextends JFrameとすべきところを
メインのクラスに合体させてしまった結果なのだ

MainクラスがAaクラスを吸収合体した結果上のコードはこう変ることになる

public class Main extends JFrame implements Runnable {
 public static void main(String[] args) {
  Main mm = new Main();//この一行にAa aa = new Aa();も一緒に入っていることになる
  Thread thrd = new Thread(mm);//mmにはaaも一緒に入っていることになる
  thrd.start();
 }
 public void run() {
  System.out.println("この辺に処理内容を書く");
 }
}
0075おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 15:17:30.36
で、結局なんの話だったかというと
そう、staticの話なのだ
static などどこにも出てきてないぢゃないか!
その通り、これから出てくるのだ

時計やら定時処理系をthreadを使って書くと
sleepメソッドを使う事になる
もちろんrunメソッドの中に書いていくことになる

public class Main extends JFrame implements Runnable {
 public static void main(String[] args) {
  Main mm = new Main();//この一行にAa aa = new Aa();も一緒に入っていることになる
  Thread thrd = new Thread(mm);//mmにはaaも一緒に入っていることになる
  thrd.start();
 }
 public void run() {
  try {
   thrd.sleep(1000); //ここ!注目
  } catch(InterruptedException e) {
   e.printStackTrace();
  }
 }
}

が、これはエラーが出てしまうのだ
0076おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 15:30:26.10
thrd が犯人なのだ

なぜならthrdはmainメソッド内で宣言されている変数であるため
runメソッドではスコープの外に置かれている
そのため利用できないのだ!

そこで、しゃーないので、こう書く

public class Main extends JFrame implements Runnable {

 Thread thrd = new Thread(mm);//←クラスブロックに移動!
 
 public static void main(String[] args) {
  Main mm = new Main();//この一行にAa aa = new Aa();も一緒に入っていることになる
  thrd.start();
 }
 public void run() {
  try {
   thrd.sleep(1000); //←thrdがスコープ内に入る!
  } catch(InterruptedException e) {
   e.printStackTrace();
  }
 }
}

しかしだ!これでもエラーが出てしまい頭を抱えてしまうだ
0077おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 15:40:22.85
犯人は mm である

Threadインスタンス宣言Thread thrd = new Thread(mm);が
クラスブロックに移動してしまったため、引数として渡しているmmが
スコープから外れてしまい、ここからではみえなくなってしまったのだ

そこでmmを定義する一行もクラスブロックに持ってくることにする


public class Main extends JFrame implements Runnable {

 Main mm = new Main();//←クラスブロックに移動! 
 Thread thrd = new Thread(mm);//←mmがスコープ内に入る!

 public static void main(String[] args) {
  thrd.start();
 }
 public void run() {
  try {
   thrd.sleep(1000);
  } catch(InterruptedException e) {
   e.printStackTrace();
  }
 }
}

しかしだ〜、まだこれでもエラーが出てしまう
0078おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 15:54:14.10
ようやくここで、static の話になるのだ

最後の犯人は、またもや thrd である

mainメソッド内の
thrd.start();
である

>>72 「staticメソッドからはstaticではないメンバを呼び出せない」

mainメソッドはstaticメソッドである
にも関わらず、staticではない thrd を thrd.start(); で呼び出しているのだ

この問題を解決するには
Thread thrd = new Thread(mm);

static Thread thrd = new Thread(mm);
とするだけではダメだ

今度はstaticな「メソッド」ではないものの、static から 非static を呼ぶという同じ現象が
static Thread thrd = new Thread(mm);
の中で起きてしまっている
staticなthrdを定義するのに非staticなmmを呼んで引数にしてしまっているのだ
そこでmmを定義する一行にもstaticを付けることにする

public class Main extends JFrame implements Runnable {

 static Main mm = new Main();//←static 
 static Thread thrd = new Thread(mm);//←static

 public static void main(String[] args) {
  thrd.start();
 }
 public void run() {
  try {
   thrd.sleep(1000);
  } catch(InterruptedException e) {
   e.printStackTrace();
  }
 }
}

これでようやく解決したのだ、ちゃんちゃん!
0079おれさま ◆6CTEZS59O00a
垢版 |
2018/10/02(火) 15:58:54.16
こやって書いているとあやふやだったところが見えてくる
実際のコードはずっと長く複雑なので、焦点を絞って小さく書き直すとなかなかいい
解決策はいろいろあるんだろうが、今の知識の範囲内で理解のできる解決策を見つけられるといいのではないかと思っている

間違えて理解しているところはあるだろうが
こうやって書いて残しておけば、そのうち気づくときもくるだろう
0081おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 13:33:30.22
staticがつくと、インスタンスが全く生成されてないのにアクセスできることになる
そのためインスタンス生成されて始めて使えるようなメンバを呼び出すことはできないし
許してはだめなのだ
だからエラーがでるのだ!
0082おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 14:18:29.06
ボタン押すと・・・・系

最も基礎レベルのコードがこれ

public class Main extends JFrame {
 Main() {
  setSize(200, 200);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JPanel pnl = new JPanel();
  JButton btn = new JButton("押して・・・・");
  pnl.add(btn);
  Container contentPane = getContentPane();
  contentPane.add(pnl, BorderLayout.CNETER);
 
  MyListener ml = new MyListener();//@
  btn.addActionListener(ml);//A
 }
 public static void main(String[] args) {
  Main ma = new Main();
  ma.setVisible(true);
 }
}
class MyListener implements ActionListener {//B
 public void actionPerformed(ActionEvent e) {
  System.out.println("あ〜ん");
 }
}
0083おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 14:28:04.79
おれのイメージだと
Aを媒介にして
@のbtnさんがBの処理系全体を背負ってるような感じ
まずこういう骨格を作る

class MyListener implements ActionListener {//B
 public void actionPerformed(ActionEvent e) {
  System.out.println("あ〜ん");
 }
} 

  __r'⌒'⌒'⌒ヽ,,_
  (,三∧_∧::: 4三) 
   ~(´∀` )爻丗 ~   MyListener ml = new MyListener();//@
   とll   lと),幵+!
((  ◯,,_ , ソ,王ノ  btn.addActionListener(ml);//A
       し"

モナーがbtnでリュックが処理系MyListener全体
リュックの肩紐がインスタンス生成の式

みたいな・・・
0084おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 14:33:15.80
ボタンを押すと・・・

モナーbtnがぴょんと飛ぶ
 ↓
するとモナーの足元で震動ActionEventのインスタンスeが自動生成されて、
 ↓
震動 e は肩紐を介してリュックに伝わる
 ↓
そしてリュックの中で震動 e を actionPerformedメソッドがキャッチして
処理が始まるみたいな・・・・



これが基礎の基礎のイメージ
ここがちゃんとできてないとすらすら書けない
0085おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 14:36:24.58
https://www.javadrive.jp/tutorial/event/index1.html
イベント処理の流れを間単に確認しておきます。

まずボタンやテキストなどのコンポーネントが何のイベントを受け取るのかを指定します。
これは例えばボタンについて考えてみると、ボタンが押されたとか、ボタンの上でマウスが
動いたなどの様々なイベントが絶えず発生していますが、必要の無いイベントについては
処理する必要が無いため、自分で処理したいイベントだけ受け取るようにするためです。


おれのSwingの教科書的サイト



ボタン押すと、ボタンからActionEentのインスタンス e が自動生成されるイメージ・・・・
0086おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 14:41:32.69
>>82-85 が一番の基礎で・・・

次がこんなの
少し変るだけ
肩紐の@がAに吸収された感じ

public class Main extends JFrame {
 Main() {
  setSize(200, 200);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JPanel pnl = new JPanel();
  JButton btn = new JButton("押して・・・・");
  pnl.add(btn);
  Container contentPane = getContentPane();
  contentPane.add(pnl, BorderLayout.CNETER);
 
  
  btn.addActionListener(new MyListener());//A
 }
 public static void main(String[] args) {
  Main ma = new Main();
  ma.setVisible(true);
 }
}
class MyListener implements ActionListener {//B
 public void actionPerformed(ActionEvent e) {
  System.out.println("あ〜ん");
 }
}
0087おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 14:58:41.37
>>86 とはちょっと別系統の発展系で、
BをMainクラスに合体させる形も考えられる

public class Main extends JFrame implements ActionListener { //BがMainに合体!
 Main() {
  setSize(200, 200);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JPanel pnl = new JPanel();
  JButton btn = new JButton("押して・・・・");
  pnl.add(btn);
  Container contentPane = getContentPane();
  contentPane.add(pnl, BorderLayout.CNETER);
 
  
  btn.addActionListener(this);//Aモナーbtn
 }
 public static void main(String[] args) {
  Main ma = new Main();//@肩紐生成はここにふくまれることになる
  ma.setVisible(true);
 }
 public void actionPerformed(ActionEvent e) {
  System.out.println("あ〜ん");
 }
}
0088おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 15:19:45.16
今は覚えちゃったから迷わないけど
ここはよく迷った

btn.addActionListener(this);//Aモナーbtn

ここのthis
このコードの体系なら

btn.addActionListener(ma); でもいいんじゃないかとか
btn.addActionListener(new Main()); とか?どうや!とかやったけどダメだった

thisにしたらうまくいったんで、そのまま思考停止してthisのままきたわけだ
ところでこのthisとは

●「自分自身のクラスのインスタンス」

そして、Main()、つまり、コンストラクタとは

●「インスタンスが生まれた直後に自動実行されるプログラム」

である。
基礎の基礎である>>82を思い出すと、thisの位置にくるのは本来は
ActionListenerを実装したクラスのインスタンス変数 ml である
>>87ではこのクラスはMainに合体しているため、ml生成の式は
Main ma = new Main(); に含まれていることになる
そしてこの式が生成されるちょうどその時に、コンストラクタMain()が呼び出されることになるのだ
いわば、maを作る時にその材料づくりとしてコンストラクタMain()の内容が処理されることになる
btn.addActionListener(ma); とすると、maをつくる材料にmaが含まれるというおかしなことになってしまうが
これは問題ない。問題なのはその書き方である
maの作成途中でmaを引き渡そうとしても、まだmaはできあがってないので引き渡せないのである
そこでthisという特殊な書き方をするのだ (とおれは考えているのだ
そもそもthisというのはそーゆーときに使うのだ! (とおれはかんがえている
わかったか!

btn.addActionListener(new Main()); はもう少しわかりやすい問題が起こる
今つくろうとしているインスタンスを引き渡したいのに、new Main()としてしまうと
別のインスタンスをあらためて作って引き渡すということになる。これはダメだ。
ちなみに、この「別のインスタンス」だが、生成するときにコンストラクタMain()を呼び出してしまう
するとまた異なるインスタンスをMainクラスから生成しようとする。そしてこのインスタンスはまた・・・・以下同様

このさまは実際にコードを実行してみるとコンソールでみられる
0089おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 15:23:39.16
ちなみにおれはSwing Javaと格闘してるのだが
最近よくきいている音楽はSwing Jazz


だから何?????とか言わないで
0090おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 15:43:14.36
>>88
> btn.addActionListener(ma); とすると、maをつくる材料にmaが含まれるというおかしなことになってしまうが
> これは問題ない。問題なのはその書き方である
> maの作成途中でmaを引き渡そうとしても、まだmaはできあがってないので引き渡せないのである
> そこでthisという特殊な書き方をするのだ (とおれは考えているのだ
> そもそもthisというのはそーゆーときに使うのだ! (とおれはかんがえている
> わかったか!。

を修正

btn.addActionListener(ma); とすると、maをつくる材料にmaが含まれるというおかしなことになってしまうが
これは問題ない。問題なのはその書き方である
thisというのはそもそもまだインスタンス化がされる前にコードに書かれるものである
基礎レベルのクラスの使い方を思い出してみるとわかるのだが
本来はMainクラスとは別のクラスファイルに書かれたクラス、
例えばHeroクラスの中でthisは使われる
そしていつかHeroクラスがインスタンス化されたときに、インスタンスが自らを利用するためにthisとして控えているのだ
thisというものはそういうものなのだ!

何が大事なのかというと、もう一度繰り返すが、thisを書いた時点では普通インスタンスは生成されていないのだ
よってインスタンス変数名など分かるはずがないのである

>>87のコードはその辺が非常に特殊であって、クラスの中で自らのインスタンスを生成しちゃってたりする
だからわかりにくい
本来はMain ma = new Main();みたいのは別のクラスに書かれるようなものなのだ
それに備えてMain側では将来作られるであろう自らのクラスのインスタンスを表す名称として
thisを使うわけだ

確かにbtn.addActionListener(ma);とするのは理屈としては間違えていないのだが
本来の使われ方からするとおかしいのでじゃばがくるくるぱ〜になってしまうのである
0091おれさま ◆6CTEZS59O00a
垢版 |
2018/10/03(水) 15:54:40.97
あーそういえば思い出した

この前こういうの書いてみたんだ

>>87に少し付け足し
public class Main extends JFrame implements ActionListener { 
 Main() {
  setSize(200, 200);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JPanel pnl = new JPanel();
  JButton btn = new JButton("押して・・・・");
  pnl.add(btn);
  Container contentPane = getContentPane();
  contentPane.add(pnl, BorderLayout.CNETER);
 
  
  btn.addActionListener(this);
 }
 public static void main(String[] args) {
  Main ma = new Main();
  ma.setVisible(true);
  Main ma2 = new Main();//←ここ
  ma2.setVisible(true);//←ここ
 }
 public void actionPerformed(ActionEvent e) {
  System.out.println("あ〜ん");
 }
}

このときにさっきの話でthisの代りにmaを使ってしまうとma2には対応できなくなってしまうんだ
だからやっぱりthisでないとダメなのだ!

ちなみにこのコードだとウィンドウが2枚開くことになって面白い
そういうプログラム作る時に使えそうだ
0092おれさま ◆6CTEZS59O00a
垢版 |
2018/10/04(木) 10:20:57.63
そして最後に、
>>86を発展させたのが下のコード
@だけではなくBまでもAに合体してしまう


public class Main extends JFrame {
 Main() {
  setSize(200, 200);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JPanel pnl = new JPanel();
  JButton btn = new JButton("押して・・・・");
  pnl.add(btn);
  Container contentPane = getContentPane();
  contentPane.add(pnl, BorderLayout.CNETER);
  
  //@+A+B
  btn.addActionListener(
   new ActionListener() {
    public void actionPerformed(ActionEvnet e) {
     System.out.println("あ〜ん");
    }
   }
  );

 }
 public static void main(String[] args) {
  Main ma = new Main();
  ma.setVisible(true);
 }
}
0093おれさま ◆6CTEZS59O00a
垢版 |
2018/10/04(木) 10:28:01.87
  //@+A+B
  btn.addActionListener(
   new ActionListener() {
    public void actionPerformed(ActionEvnet e) {
     System.out.println("あ〜ん");
    }
   }
  );

この部分はモナーbtnがリュックを背負ってる部分がセットで表現されている
発展形態とはいえ、もっともわかりやすい
しかし、ここで、あれ?っと疑問が出てくる
@、A、Bが結合しているあたりのコードがおかしいのではないか
本来こう書かなければいけないのではないか?

  //@+A+B
  btn.addActionListener(
   new MyListener() implements ActionListener { //←このへん
    public void actionPerformed(ActionEvnet e) {
     System.out.println("あ〜ん");
    }
   }
  );

ActionListenerのインスタンスではなくActionListenerを実装したクラスのインスタンスを
生成しなければならないのだから。

しかし、このように書くとエラーが生じる 👀
Rock54: Caution(BBR-MD5:1341adc37120578f18dba9451e6c8c3b)
0094おれさま ◆6CTEZS59O00a
垢版 |
2018/10/04(木) 10:51:55.08
この辺を理解するにはある原則的なルールを覚える必要が出てくる

このようなbtnにクラスから全部背負わせてしまうようなコードには名称がついている
正確には、背負われているクラスの名称なのだが、「匿名クラス」とか「無名クラス」と呼ばれる

匿名クラスには大事なルールがある。
それは、
「new クラスA(インターフェースA)」 とした場合
クラスAをnewすることにはならないのだ(インターフェースはそもそもnew出来ないのが基本)
そうではなく、
●「クラスAまたはインターフェースAを継承または実装した」クラス をnewすることになるのだ

なぜだか理由はよく分からないが
>>93の下の方のコードにエラーが出てしまうように、implementsを記述できないからなのだろうか

なにはともあれ、このルールを前提に考えれば

  btn.addActionListener(
   new ActionListener() {

の2行目は、「インターフェースActionListenerを実装したクラスをnewする」、という意味になる
つまり最も基礎的なコードである>>82の@new MyListenerと全く同じことを意味するのだ

参考までにいえば、
もしスーパークラス(ここでいうならActionListener)の中で
private修飾子のついたフィールドが宣言されていると、
newしたあとのブロック内ではこのフィールドにアクセスできないことになってしまうのだ

ちゃんと書こう
クラスAAでaというフィールドがこう宣言されていたとする
private int a;
このとき匿名クラスを利用し、こう書いたとする

new AA() {
 public void bb() {
  a = 10;
 }
}

これはエラーが生じてしまう
なぜならnewしたのはAAのように見えて実はAAを継承した別の(名無しの)クラスだからだ
名無しの別のクラスからはAA内に宣言されたprivate変数にアクセスすることは許されないのだ
0095おれさま ◆6CTEZS59O00a
垢版 |
2018/10/04(木) 10:56:23.17
まぁだからこそ「匿名」クラスという名前がついている

new AA が
クラスAAをnewするというのであれば
AAって名前あるじゃん・・・となる
しかし
new AA が
クラスAAを継承した名無しクラス
または
インターフェースAAを実装した名無しクラス
をnewするという意味だとしたら
まさに匿名っすよね!
0099おれさま ◆6CTEZS59O00a
垢版 |
2018/10/05(金) 12:37:34.40
さて、今日からは

フレーム上で右クリックメニューを表示させ、
「閉じる」の項目を選択・クリックしてプログラムを終了させる処理

について再考する

この処理はすでに作ったソフトで利用してはいるが
理解を深めるために他の処理とは独立した形でとりだして分析すべきだと思っている
先を急いだため、コピペでしのいだ部分もあり、
部分的には理解できていない可能性があるのだ
0100おれさま ◆6CTEZS59O00a
垢版 |
2018/10/05(金) 12:53:55.83
ところで、なぜ右クリからの終了処理が必要になったのかというと
windowsアプリは通常タイトルが表示される枠部分がある
そしてこのタイトルの右の端には最小化・最大化・閉じるボタンがあるのだ
閉じるボタンがあればわざわざ右クリから閉じる機能を作る必要もない

しかし、小さなウィンドウのプログラムを作るときは、このタイトルバーが邪魔になってしまう
右端の3つのボタンはウィンドウをより小さくする時に障害となってしまうのだ

おれが作ったものはこういうもの
https://dotup.org/uploda/dotup.org1659204.jpg
昭和チックな絵柄でデザインセンスが皆無なのが分かるだろうか
いやそういう話ではなく、ウィンドウを小さくするためにタイトルバーを取り外してしまったわけだ
すると、
setDefaultCloseOperation(true); が機能しなくなってしまうのだ

それどころか、ウィンドウの位置を動かすことすら出来なくなってしまう
つまり、タイトルバーを消してしまった代償として、以下の2つの機能を実装する必要があるのだ

1.閉じる機能を右クリメニューに加える
2.ウィンドウをD&Dにより動かせるようにする

今回は1.について分析をしていこうとおもうとる
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況