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版 (スッキリシリーズ)
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.について分析をしていこうとおもうとる
0101おれさま ◆6CTEZS59O00a
垢版 |
2018/10/05(金) 16:01:38.75
分析大体終了

右クリして閉じる機能は大きく2つに分けて考えるといい
イベント処理が2つあるのでこの2つを分けて考えるのだ

イベント処理というのはつまり >>82-85 と同じ
モナーが肩紐を肩にかけてリュックを背負ってるイメージ
これが2段構えになっている
モナーが背負ったリュックの上に別のモナーが別のリュックを背負ってる感じ

一つ目の処理は
右クリックをして何かが起きるまで

二つ目の処理は
項目がポップアップし、「閉じる」を選択することでフレームが閉じるまで
0102おれさま ◆6CTEZS59O00a
垢版 |
2018/10/05(金) 16:04:25.90
>>83だけどちょい間違えてるな

Aを媒介にして
@のbtnさんがBの処理系全体を背負ってるような感じ
 ↓
@を媒介にして
AのbtnさんがBの処理系全体を背負ってるような感じ
0103おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 07:51:35.99
最も基礎的なコードを書こうとして逆に迷う

これまでdispose()をプログラム終了のために使ってきたが、Mainとは別のクラスから使おうとするとなかなかうまくいかない
System.exit(0); を使う事で問題を回避できたのだが、原因はなんだったのかなといろいろ考えてる

このサイトでの記載がキーになるのではないかと思っている
http://www2n.biglobe.ne.jp/~fify/shiroutoshikou/java/api/java/awt/Frame.htm

終了処理にはSystem.exit()ではなくdispose()を使っています。
System.exit()はJava仮想マシンの終了を意味しますが、
dispose()はメソッド呼び出し元のウィンドウおよび、
そこから呼び出されているすべてのコンポーネントを解放し、
メモリ資源をOSへと返却します。ここで行いたいのは
Java仮想マシンの終了ではなくFrameを閉じることなので、
dispose()を使うのが作法的にも正解です。

クラスの内部でさらにクラスを定義していることに注意してください。
ここで、先ほどのクラスWinLのようにメソッドwindowClosing()を
オーバーライドしたクラスを用意してフレームを表示するクラスから呼び出そうとしても、
コンパイルエラーとなります。なぜなら、メソッドdispose()は
抽象クラスWindowAdapterおよびその親クラスには実装されていないからです。
メソッドdispose()が実装されているのは、Frameの親クラスであるjava.awt.Windowとなります。
0104おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 07:56:02.00
やはりよくわからない
が、まぁいいだろう
今回焦点を当てたいのは終了処理ではないのだ
0105おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 07:57:52.12
さて、気を取り直して、
右クリから終了するコードを書く
これがおれ史上もっとも基本的なコードとして頭にたたき込んでおくものとする

public class Main extends JFrame {

static JPopupMenu pm = new JPopupMenu();//C

Main() {
setSize(100, 100);
setLocationRelativeTo(null);

MyMsListener ml = new MyMsListener();//A
addMouseListener(ml); //@

MyAcListener al = new MyAcListener(); //G
JMenuItem mi = new JMenuItem("閉じる");//E
mi.addActionListener(al); //F
pm.add(mi); //D
}

public static void main(String[] args) {
Main ma = new Main();
ma.setVisible(true);
}
}

class MyMsListener implements MouseListener { //B
public void mouseClicked(MouseEvent e) {
if(SwingUtilities.isRightMouseButton(e)) {
Main.pm.show(e.getComponent(), e.getX(), e.getY());
}
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
class MyAcListener implements ActionListener { //H
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
0106おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 08:00:15.68
いや、タブを全角スペースに直すの忘れてたんで再度こぴぺ

右クリから終了するコードを書く
これがおれ史上もっとも基本的なコードとして頭にたたき込んでおくものとする

public class Main extends JFrame {
 
 static JPopupMenu pm = new JPopupMenu();//C
 
 Main() {
  setSize(100, 100);
  setLocationRelativeTo(null);
  
  MyMsListener ml = new MyMsListener();//A
  addMouseListener(ml); //@
  
  MyAcListener al = new MyAcListener(); //G
  JMenuItem mi = new JMenuItem("閉じる");//E
  mi.addActionListener(al); //F
  pm.add(mi); //D
 }
 
 public static void main(String[] args) {
  Main ma = new Main();
  ma.setVisible(true);
 }
}

class MyMsListener implements MouseListener { //B
 public void mouseClicked(MouseEvent e) {
  if(SwingUtilities.isRightMouseButton(e)) {
   Main.pm.show(e.getComponent(), e.getX(), e.getY());
  }  
 }
 public void mousePressed(MouseEvent e) {}
 public void mouseReleased(MouseEvent e) {}
 public void mouseEntered(MouseEvent e) {}
 public void mouseExited(MouseEvent e) {}
}
class MyAcListener implements ActionListener { //H
 public void actionPerformed(ActionEvent e) {
   System.exit(0);
 }
}
0107おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 08:35:28.74
>>106
おれの感覚では

T @〜Bが右クリから何かを起こすまでの処理
U C〜Hが右クリメニューがポップアップしてから実際のプログラム終了までの処理

というように2つの段階があると捉えている


Tは
@(JFrame).addMouseListenerのモナーが
A肩紐ml宣言を通じて
BリュックであるMouseListenerを実装した実際の処理を背負っている
イメージで捉える

フレーム全体にわたってマウスの動きを感知する機能が加えられる
フレーム上でマウスがクリックされると、その震動 e が肩紐Aをつうじて
リュックにつたわりBの実際の処理へとつながる
このとき e がマウスのどの種類のクリックだったのかを分析して
if 文により、それぞれの処理を個別に指定できる
ここでは e が右クリにより生じたとするなら、pmを特定位置でshowしろと指示する


Uは
CDEpmが何なのを説明し、miまでつながる道筋を示す
Fmi.addActionListenerのモナーが
G肩紐al宣言を通じて
HリュックであるActionListenerを実装した実際の処理を背負っている
イメージで捉える


CDEは一応Uに含まれるようなイメージで捉える
Tでの実際の処理としてpmがshowするのだが
pmを宣言するのがC、pmとはJPopupMenu
つまり右クリしたときにぽよんとあらわれる「あれ」の本体とイメージする
「あれ」(JPopupMenu)は当初は姿形がなく、
ここに項目JMenuItemが加えられることで目視できるようになる
JMenuItemは今回のプログラムでは1個だけで、「閉じる」 の項目を示すために使う
「他地域の天気」などの別の項目を加えたいのであれば複数のJMenuItemを宣言し
これを、目では見えないがぽよんの本体であるpm(JPopupMenu)にaddすることになる

mi(JMenuItem)は宣言時に表示文字列をコンストラクタに渡すことになる
そしてこのmiがTのモナーが背負うリュックのさらに上に立つモナーとなるのだ

このmiは>>82-85のbtnと全く同じ位置づけと考えればよい
Fmi.addActionListener(al);というモナーが
G肩紐al宣言を通じて
Hリュックである実際の処理を背負う構図だ

「閉じる」の項目をクリックしたとたんに震動 e がFモナーの足元で生じ
これがGを通してHに伝わり、最終的に e を受けとったactionPerformedメソッドが
System.exit(0)を実行し、プログラムが終了するのだ
0108おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 08:48:05.81
このコードの形式を前提とするなら
右クリメニューを増やすごとに
D〜Hを変数名等を変えて書き足すことになる

しかし、これでは面倒ではないか?コードが読みにくくなるのではないか?
という批判に応えるため、クラスを活用したコードを書くのが一般的のようだ
0109おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 08:50:36.77
ただし、それはもう少し後に回すことにして
>>106を匿名クラスを使って書き直したものを貼ることにする
イベント系の処理は基本的には匿名クラスを使って書くようにしていこうと思っている

public class Main extends JFrame {
 
 JPopupMenu pm = new JPopupMenu(); //C
 
 Main() {
  setSize(100, 100);
  setLocationRelativeTo(null);

  addMouseListener( //@
   new MouseListener() { //A+B
    public void mouseClicked(MouseEvent e) {
     if(SwingUtilities.isRightMouseButton(e)) {
      pm.show(e.getComponent(), e.getX(), e.getY());
     }      
    }
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
   }
  );
  
  JMenuItem mi = new JMenuItem("閉じる"); //E
  mi.addActionListener( //F
   new ActionListener() { //G+H
    public void actionPerformed(ActionEvent e) {
      System.exit(0);
    }
   }
  );
  pm.add(mi); //D
  
 }
 public static void main(String[] args) {
  Main ma = new Main();
  ma.setVisible(true);
 }
}
0110おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 09:07:46.99
>>107
修正

BリュックであるMouseListenerを実装した実際の処理を背負っている

BリュックであるMouseListenerを実装したクラスMyMsListenerが実際の処理を背負っている


HリュックであるActionListenerを実装した実際の処理を背負っている

HリュックであるActionListenerを実装したクラスMyAcListenerが実際の処理を背負っている
0111おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 09:16:12.97
さて、先ほど書いた 「クラスを活用したコード」 とは、匿名クラスのことではない
自作のクラスを作成し、自作クラスのインスタンスを複数生成することで
複数の右クリメニューを作って行くという方法である
このタイプの書き方をすることで、右クリメニューの項目が
各インスタンスのnewごとに羅列されるため、見た目わかりやすい

しかし、おれみたいなレベルのプログラマーにとっては匿名クラスで書いた>>109を前提に
右クリメニューを増やしたほうがわかりやすかったりもする
メモリの使い方なんやらでやはり自作クラスを使うべきなんだろうが。

匿名クラスでメニューを増やすなら
D〜Eのブロックをメニューごとに増やすことになる
もちろん変数名などは変えていかねばならぬ
0112おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 09:30:34.08
例えばこんな感じだ

最終的な処理がより複雑になりコードが長くなった場合
わかりにくいコードになってしまう点は否定できないのだが

public class Main extends JFrame {
 
 JPopupMenu pm = new JPopupMenu(); //C
 
 Main() {
  setSize(100, 100);
  setLocationRelativeTo(null);

  addMouseListener( //@
   new MouseListener() { //A+B
    public void mouseClicked(MouseEvent e) {
     if(SwingUtilities.isRightMouseButton(e)) {
      pm.show(e.getComponent(), e.getX(), e.getY());
     }      
    }
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
   }
  );
  
  JMenuItem mi = new JMenuItem("閉じる"); //E
  mi.addActionListener( //F
   new ActionListener() { //G+H
    public void actionPerformed(ActionEvent e) {
      System.exit(0);
  }});
  pm.add(mi); //D
  
  JMenuItem mi2 = new JMenuItem("サイズを大きくする"); //E
  mi2.addActionListener( //F
   new ActionListener() { //G+H
    public void actionPerformed(ActionEvent e) {
      setSize(300, 300);
  }});
  pm.add(mi2); //D
  
 }
 public static void main(String[] args) {
  Main ma = new Main();
  ma.setVisible(true);
 }
}
0113おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 09:34:35.47
ちなみに、「サイズを戻す」 というメニューを追加すると
5チャンで書込みがロックされてしまうため項目は2つに留めておいた
繰り返し似た文を書くと駄目なようだ

ロックされた場合は
https://agree.5ch.net/mango/
この板で試行錯誤を繰り返しながら原因把握ができる


コードは繰り返しの文が多くなるので引っかかりやすいかもしれない
0114おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 09:48:48.02
Javaでつくったwindowアプリの右クリメニューがひどいデザインなのは仕方ないのか?
Swingだとこうなってしまうのか、、、、?
0115おれさま ◆6CTEZS59O00a
垢版 |
2018/10/06(土) 16:00:19.81
右クリから閉じる機能の説明はまだ終わってないのだが
>>100に書いた 「ウィンドウをD&Dで動かす機能」 について先回りしてざっとみている

自分が書いたコードは試行錯誤しながらコピペしまくったせいか
不必要な部分がいくつも見つかった

D&D移動機能については別の機能との関連もあって、頭の中でまったく整理できていない
とくに注目しなければならない「別の機能」とは、
前回閉じた位置で開く機能である

この機能は大まかに説明すれば
ウィンドウを閉じるときにiniファイルに現在座標を記録し
次に開くときにiniファイルから座標を読み込んで、同じ位置に開くというものだ

と、書いたのだが正確にいうとiniファイルに書き込むタイミングはウィンドウを閉じる時ではない
プログラムは予期せぬトラブルによって終了してしまうおそれがある
そこで、ウィンドウ位置が動いた場合、そのたびにiniファイルに場所を記録するのだ
こうすることでトラブル対策になる

そのためD&D機能との関連が大事になるのだ

ちゃんとまとめれば、そう難しいものではないと思うのであせらずやっていこう
すべての機能が整理できたあと、もう一度最初から全部書き直すといいのだが
その気があればやることにしよう
0116おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 04:33:03.57
>>108
>>111
の修正

「クラスを活用したコード」
は間違いだった
実際に書いてみたところ、クラスではなく、「メソッドを活用したコード」だった
右クリメニューの項目を増やすごとに
文字列とActionListenerのインスタンスをメソッドに引数として渡す
0117おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 04:42:50.17
実際に書いていくとこういうものになる
>>109をさらに発展させたといえるのだろうか

public class Main extends JFrame {
 
 JPopupMenu pm = new JPopupMenu(); //C
 
 Main() {
  setSize(100, 100);
  setLocationRelativeTo(null);

  addMouseListener( //@
   new MouseListener() { //A+B
    public void mouseClicked(MouseEvent e) {
     if(SwingUtilities.isRightMouseButton(e)) {
      pm.show(e.getComponent(), e.getX(), e.getY());
     }      
    }
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
   }
  );
  addMi("閉じる",
   new ActionListener() {//G+H
    public void actionPerformed(ActionEvent e) {
     System.exit(0);
  }});
  
  addMi("サイズを大きくする",
   new ActionListener() {//G+H
    public void actionPerformed(ActionEvent e) {
     setSize(300, 300);
  }});

 }
 public static void main(String[] args) {
  Main ma = new Main();
  ma.setVisible(true);
 }
 public void addMi(String name, ActionListener al) {
  JMenuItem mi = new JMenuItem(name);//E
  mi.addActionListener(al);//F
  pm.add(mi);//D
 }
}
0118おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 04:58:55.11
>>117は、@〜Cまではこれまでと同じなのだが、それ以降のD〜Hが違う

まだ目に見えないJPopupMenuに各項目を加え実際の処理につなげていく部分なのだが
そのうち、GActionListener実装クラスのnewとH実際の処理部分だけを項目ごとに書き、
言い換えると、G肩紐とHリュック部分だけを項目ごとに書き、
その他の部分は共通部分としてメソッドにまとめることになる

こうすることで>>112のように項目を増やすごとに変数をあらたに作っていく必要がなくなる

正直言ってこうすることでどれだけのメリットがあるのかは、今のところよく分からない
右クリメニュー機能をつくるために検索した結果、
お手本としたのがこの手のタイプのコードだった
これを理解することを目標に書いてきたので、とりあえず目的達成ということでいいだろう
これから先、右クリメニューのコードを書くときは
これをベースに書いていけるといいなと
0119おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 05:26:49.45
次に行こう

ウィンドウのD&D移動である
これまで書いてきた処理のほとんどはイベント系の処理だ
D&D移動もイベント系の処理の一つである
パターンがつかめてくると、理解するまでのスピードが速くなってくる

D&D移動の処理も3つのイベントに区分できる

T マウスを押す
U そのままマウスを動かすことでウィンドウがうごく
V マウスを放す

それぞれの処理を引き受けるインターフェースは
T MouseListener
U MouseMotionListener
V MouseListener
ということになる

TとUは同じMouseListenerを使うため、コードはまとめることができるだろう
0120おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 05:31:13.22
ウィンドウD&D移動

public class Main extends JFrame {
 
 static Point pt;
 
 Main() {
  setSize(100, 100);
  setLocationRelativeTo(null);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
  addMouseListener(
   new MouseListener() {
    public void mouseClicked(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {//@
     pt = e.getPoint();
    }
    public void mouseReleased(MouseEvent e) {//B
     pt = null;
    }
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
   }
  );
  addMouseMotionListener(
   new MouseMotionListener() {
    public void mouseDragged(MouseEvent e) {//A
     Point currentPt = e.getLocationOnScreen();
     setLocation(currentPt.x - pt.x, currentPt.y - pt.y);//
    }
    public void mouseMoved(MouseEvent e) {}
   }
  );
 }
 
 public static void main(String[] args) {
  Main ma = new Main();
  ma.setVisible(true);
 }
}
0121おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 05:58:02.92
一気に匿名クラスを使った最終版を書いたわけだが
基本的にはこれまでとパターンは同じだ

細かい処理が違ってくるだけだ
まずここで使っているPointというクラスが大事だ
簡単にいえばデスクトップ上の(x, y)座標を格納してくれるインスタンスを生成できるクラスなのだ
正確にいうと、デスクトップ上の(x, y)座標は絶対座標というが、
Pointのインスタンスは相対座標も格納できる
今回使われる相対座標は、マウスをウィンドウ内でクリックしたとき、マウスの座標を
ウィンドウの左上端から測った相対座標である

Pointインスタンスに格納された座標をStringで表示するには
Point pt = new Point();
pt = e.getPoint();
を前提とするなら
System.out.prinln(pt.x);
System.out.println(pt.y);
System.out.println(pt);
のどれでもOKだ。一番下のものはtoStringの機能が自動で使われており便利だ

相対座標を取得するメソッドはgetPoint()
絶対座標を取得するメソッドはgetLocationOnScreen()

どちらもActionEvent e つまり「震動」の発生地点の座標を測ることになるので
e.getPoint()
e.getLocationOnScreen
のように e を基準としてコードを書くことになる


T〜Vの処理を細かく見ていく

T→@
マウスを押すことでウィンドウ左上端から測ったマウスの相対位置をptに格納
相対座標はAで使うためにここで取得している

U→A
ドラッグするごとに変化するマウスの位置をcurrentPtに格納していくと同時に
currentPtに応じてウィンドウの位置を設定していく
setLocationにはウィンドウの左上端となる座標を渡さないといけないので
currentPtから相対座標分だけずらした座標を計算してわたすことになる
マウスの座標をそのまま渡してはいけない点に注意しなければならない

V→B
ptにnullを入れる
ちなみにB処理だが、pt = null; をコメント行にしても正常に動いた
pt = null:が必須なのかはよくわからない
少なくとも、ptを他の処理に使い回したい場合にはこうして置いた方がよいのかなと思った
0122おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 06:19:32.74
yahooから明日のお天気を取得するソフトがらみで
おさらい分析しなければならない最後の部品に取りかかろう

「前回閉じた場所に開き直す」 機能

テキストファイルに座標を書き込む・読み込む
ウィンドウ位置が変ったときにiniファイルに座標をかき込むなど
まだ苦手としている処理が含まれている
0123おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 07:49:42.28
そのまえに座標の取得について

e からx座標、y座標を取り出す方法なのだが
さきほど使ったのは一旦Pointインスタンスに格納する方法
相対座標に絞って説明するが

Point pt = e.getPoint():
int x = pt.x;
int y = pt.y;

Pointインスタンスを使わないでも
e から直接x座標、y座標を取り出すことは可能だ

int x = e.getX();
int y = e.getY();

これは「右クリから閉じる機能」>>117で使ったものだ
2つの方法を混同して使わないようにしなければならない

ところで、この方法どちらもだが、相対座標を取り出すのに使われるのだが
何を原点(0, 0)とするのかを明確にする必要がある
これについては
「発生元のコンポーネントを基準とする、イベントの相対 x、y 座標値」
と考える
ここでいう発生元とは、e がどこから発生したのか、である

btn.addActionListener 
ならbtnということになるのだろう
btnの左上端を基準に測ってくれるのだろうか(未確認)

this.addMouseListener
this.addMouseMotionListener 
ならthisということになる
このthisだが、>>120では使ってはいないものの
コンストラクタの中にあるaddMouseListenerやaddMouseMotionListener
の前にthisをつけるのが本来の書き方じゃないかと思っている
実際、エラーはでない
thisは「自分自身のクラスのインスタンス」を意味するため、ここでは ma がそれにあたる
MainがJFrameを継承しているから、maはJFrameのインスタンスでもある
つまり
this.addMouseListenerとした場合の e の発生元はthis=ma=JFrame=フレームそのものと考えられる
こうすることで
この場合の e.getX()は
フレーム(ウィンドウ)の左上端を原点とした場合のマウス位置の相対座標をかえすことになる
0124おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 08:46:22.97
ついでなのだが、右クリ閉じる機能>>117
pm.show(e.getComponent(), e.getX(), e.getY());

showメソッドは、JPopupMenuを表示するためのメソッドである

「イベントを発生させたComponentオブジェクト」内の
(x, y)座標で指定された位置にJPopupMenuを表示する
(x, y)はレファランスで読む限り相対座標でなければならないようだ

e.getComponent() は「イベントを発生させたComponentオブジェクト」を取得
e.getX() は「イベントを発生させたComponentオブジェクト」内での相対座標xを取得
e.getY() は「イベントを発生させたComponentオブジェクト」内での相対座標yを取得

少し脱線するのだが
getComponent()について疑問が残った

ActionEvnetのインスタンスである e についてのメソッドだろうと思って
ActionEventを調べてみたところこのようなメソッドはなかった
どうやら、ComponentEventという別のクラスのメソッドであるようだ
ComponentEventはActionEventによって継承なり実装されてるのかとおもいきや、そうでもない
なぜ e.getComponent() という書き方ができるのか、今の知識では理解できない
これは後回しにしておこう
いずれ理解できるのかもしれない
0125おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 11:50:34.72
>>124はちょっと勘違いしてた

>>117
pm.show(e.getComponent(), e.getX(), e.getY());
で使っている e はActionEventではなくてMouseEventだった
MouseEventをAPI referenceでみてみると

java.awt.event
クラスMouseEvent

  java.lang.Object
     java.util.EventObject
        java.awt.AWTEvent
           java.awt.event.ComponentEvent ←ここ
              java.awt.event.InputEvent
                 java.awt.event.MouseEvent ←ここ

となっており、MouseEventの親のそのまた親にComponentEventがある
つまり、この繋がりがあるからMouseEventのインスタンス e はComponentEventで
定義されている getComponent()メソッドを利用できるというわけだ

実際にreferenceにもこう書いてある

クラス java.awt.event.ComponentEventから継承されるメソッド
getComponent

な〜んだな〜んだ
そう難しい話ではなかった
0126おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 12:39:28.20
またまたついでだが
>>117の自作メソッドを使ったパターンについて自分なりのとらえ方というか考え方を書く

自作メソッドの部分
 public void addMi(String name, ActionListener al) {
  JMenuItem mi = new JMenuItem(name);//E
  mi.addActionListener(al);//F
  pm.add(mi);//D
 }
モナーがリュックを背負っている形をつくり
さらにそのモナー全体がJPopupMenuに加わるという
メインの処理は、ここだけで終わっていると考える

そのうえで、addMiを呼び出すこの部分↓はどう捉えるのかというと

  addMi("閉じる",
   new ActionListener() {//G+H
    public void actionPerformed(ActionEvent e) {
     System.exit(0);
  }});

メインの処理の中で、ある変数を利用することで詳細を省いた部分がある
そこを埋めるため、あとからジグソーパズルのピースをはめ込むような処理を担っているとする

欠けていたピースは2つあり、
一つは
本来JMenuItemインスタンス生成時にコンストラクタに
渡すはずの項目名称をnameという変数をつかって空欄状態にしてあった部分
もう一つは
本来addActionListenerの引数として実際の処理を含めた形で匿名クラスのインスタンスを
渡すはずが al という変数を使って空欄状態にしてあった部分

この2カ所に実際のピースをはめたのがaddMiの呼び出し部分と捉えることにする
0127おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 12:50:20.67
基礎レベルのコードからいくつかの高度化を経てたどり着いた雛形となるコードは
そらで書けるようになんどか繰り返して書くことにする
ただし、インターフェース実装によりオーバーライドが必要なメソッド群については
eclipseのTODOに頼ることにする
import文も同様にeclipseに頼ることにする
それ以外は何も見ずに書けるようにする

Swingは今後どう扱われているかはわからないものの、
今となっては時代遅れな代物に成りはてている
Java自体もそうなりつつあるのかもしれない

しかし、今後どのような言語を学んでいくとしても
Javaに代表されるような主要言語の体系は引き継がれていくと予想される

JavaのSwingを使った時はこういう風に書いたなという明確なイメージが
頭にあるのとないのとでは全く違ってくるのではないか
そこでいくつかの基本パターンについてはしっかりと暗記してしまおうと思っている
0128おれさま ◆6CTEZS59O00a
垢版 |
2018/10/07(日) 15:39:47.30
>>122にとりかかっているんだけど今知ったことがある

https://www.sejuku.net/blog/20794
プログラミング言語のなかでもC++などは、拡張子を「.ini」とした設定ファイルを
読み書きする関数が用意され、それを利用しています。
Javaの場合は、拡張子が「.properties」のプロパティファイルに定数などの
規定値や、ファイルのパスなどをまとめて記載し、読み書きするのが一般的です。



な、なんだって〜
iniファイルってC系の設定ファイルだったのか
Javaではpropertiesを使うとは!

もしかして〜と思って実践編をぺらぺらめくってみたら10章に書いてあった
あれかね、やっぱりこの一冊ちゃんと読んでから分析したほうがいいかな
0129おれさま ◆6CTEZS59O00a
垢版 |
2018/10/08(月) 14:16:47.38
properties便利だわぁ
iniよりずっと難易度下がった

前閉じた場所で開くコードは長くなるんで、今のところはここには書かない
プログラムを大きく分けるとこうなる

T プロパティファイルを読みにいってウィンドウを開く部分
U ウィンドウが動くたびに変数に数値を格納して閉じるときにプロパティファイルに記録する部分

Tについてプロパティファイルを読むためにクラスを自作して
座標と幅・高さに関するフィールドを置く
このクラスはmainメソッドはなく、フィールドに値を突っ込むためのコンストラクタだけ。

Uでプロパティファイルに記録する部分は、Mainクラス内にメソッドを設ける


読み込む時だけクラスをつくって書き込む時はメソッドにしたのは何となく書きやすかったと理由にすぎない
0130おれさま ◆6CTEZS59O00a
垢版 |
2018/10/08(月) 14:22:21.54
もう一つだけ暗記のベースにするためのコード作っておくか

HTMLを取得してタグで分割して配列に格納する

これだけやったらテキストに戻ろう
0131おれさま ◆6CTEZS59O00a
垢版 |
2018/10/09(火) 07:46:04.44
ウェブスクレイピング(英: Web scraping)とは、
ウェブサイトから情報を抽出するコンピュータソフトウェア技術のこと。
ウェブ・クローラーあるいはウェブ・スパイダーとも呼ばれる。
0132おれさま ◆6CTEZS59O00a
垢版 |
2018/10/09(火) 14:39:29.35
ひょんなことからWSH windows shell hostのVBScriptをちょっとだけやってみた
HTML取得したりもできるのかな?と思って調べてみたら
HTMLを専門に扱う目的でプロパティやメソッドが用意されている
これはもしやJavaでもあるのではないかと思って調べてみたら、やっぱりあった

Java ウェブスクレイピング

でぐぐるといろいろ出てくる

「HTMLパース」
HTMLパースとは、HTML文法規則にのっとった文字列を、その文法に基づいて字句解析し、
意味や構造を解釈することをいい、HTMLパースを行うプログラムのことをHTMLパーサといいます 

パースはparse、構文解析
parseIntのparseか

JavaのHTML paserとしては
「Jsoup」 (じぇぃすーぷ)
がいまのところ有力だそうで。
導入方法がいままでみたことがない方法だ
外部ライブラリというのかな

https://qiita.com/Terry3/items/0c1829130111967773bf
eclipseへの導入はここがわかりやすいか?
あとでやってみようか
0134おれさま ◆6CTEZS59O00a
垢版 |
2018/10/09(火) 14:52:15.89
>>133は違うな
これはScalaとかKotlinという別の言語でJsoupを利用しているようだ
Java以外からも利用できるライブラリなんだな
0135おれさま ◆6CTEZS59O00a
垢版 |
2018/10/09(火) 17:12:28.69
FileOutputStream ファイルに書く
FileInputStream ファイルを読む

逆にしてしまいがち
0136おれさま ◆6CTEZS59O00a
垢版 |
2018/10/09(火) 17:29:50.82
スッキリ実践編260ページ
FileReaderやFileWriterで、コンストラクタの引数に文字コードを指定することができると
読み取れるような文章があるんだけど、これできないよね

https://uxmilk.jp/47743
FileWriter クラスは文字コードを指定することができないので、
文字コードを指定するときは、
OutputStreamWriter

FileOutputStream
を使用します。
OutputStreamWriter のオブジェクトを生成するときに、第2引数に文字コードを指定します。
0137おれさま ◆6CTEZS59O00a
垢版 |
2018/10/09(火) 17:32:01.15
File f = new File("sample.txt");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(f), "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);

bw.write("1行目");
bw.newLine();

bw.close();


こういうのを使えば簡単に人が集まるんでしょうね
じゃなくて
こういうのを使えばプロパティファイルの日本語文字化けの問題にも対処できるんかなとか思ったりしたんだけど
0138おれさま ◆6CTEZS59O00a
垢版 |
2018/10/09(火) 18:08:24.09
File f = new File("save.properties");
if (f.exists) {}

みたいな感じでFileクラス使ってきたけど
Path と Files を使っていくことにした

Path p = Paths.get("save.properties");
if (Files.exists(p)) {}

ポイント:
・Pathはインターフェースなのでインスタンスをnewできない
その代りにPaths.get()を使う事でPathインスタンスを取得する
・Filesはインスタンスを生成しないでクラスを直接使ってメソッドにアクセスする

ぶっちゃけFileを使った方がわかりやすいんだが
0139おれさま ◆6CTEZS59O00a
垢版 |
2018/10/09(火) 19:16:12.35
public static final String st = "あああ";

定数であることはfinal修飾子だけで表現できますが、
static修飾子を付けるのがお作法です。static修飾子を付与することで、
インスタンス生成のたびに同じ値をインスタンスにコピーするのを防ぐことができます。


インスタンス生成のたびに同じ値をインスタンスにコピーするのを防ぐことができる
インスタンス生成のたびに同じ値をインスタンスにコピーするのを防ぐことができる

これ大事
0140おれさま ◆6CTEZS59O00a
垢版 |
2018/10/10(水) 02:34:35.36
パブリックスタティックファイナルストリング!すたっ!ああああああああぁぁぁぁぁっぁ!!!!
(変身
0141おれさま ◆6CTEZS59O00a
垢版 |
2018/10/10(水) 09:31:15.40
プロパティファイルの読み書きに関してはみんないろいろ工夫してるんだな
いろんなコードみてきたんだけど、おれの用途だと
技が高度すぎてちょっとここまでしないでもいいかなと思えるものが多い
部分的に参考にしたらよさそうなのはあった

読み込みのクラス作って
コンストラクタでPropertiesをnewしてloadするところまでやる
このクラス内でゲッターみたいなメソッドを作って引数にキー名を指定して
戻り値で値を返すみたいな。

書込みについてはまだ調べてないが
書込みのクラス作ってから
コンストラクタでPropertiesをnewしておいて
セッターみたいなメソッド作って、引数にキー名と値を指定とかかな
値に関しては最終的にはStringにしないといけないんだけど
当初はintだったりStringだったりするわけだから
型によって複数のメソッド作ったりするんかな
0142おれさま ◆6CTEZS59O00a
垢版 |
2018/10/10(水) 09:41:36.02
https://nompor.com/2017/11/26/post-1430/
2018/08/03・・・PropertiesにはReaderやWriterを引数にすることもできます。こちらを利用して文字コードを指定すれば、日本語の表示も可能です。

どこかに同じようなことが書いてあったけど
ちょっとやってみよう
じゃなぜみんなFileReaderやFileWriterを使うんだろうかと思うと
やはりデメリットがあるんだろうな
0143おれさま ◆6CTEZS59O00a
垢版 |
2018/10/10(水) 10:03:14.29
>>141
いやいや、書込みをこの方法で作っちゃうと
インスタンス生成したのはいいがメソッドを使わなければcloseされないという問題が起きるぢゃんか

メソッド単位でFileWriterのnewとclose処理すれば良いんだけど
newというものはそこそこ重い処理だなんてことをどこかで見て以来
こういう連続した処理でそのたびにnewするのはだめなのかなとか思っちゃう
どうなのかね
0144おれさま ◆6CTEZS59O00a
垢版 |
2018/10/10(水) 10:09:22.18
と、ここまで考えて気づいたのは、closeしないまま終わるのは
書込みだけじゃなくて読み込みもだ

参考にしたコードをもう一度見直してみたんだけど
なんと、このコードはFileWriterとかFileReader使ってない
結局closeの問題を避けるためにこういう方法があるのかな
0145おれさま ◆6CTEZS59O00a
垢版 |
2018/10/10(水) 10:20:40.84
ん〜やっぱりわかんないや
お手本のコードもう一度見直したらthrows IOExceptionしてる
読み込みや書込みのクラス内で例外処理も完結してくれないといやだいやだ
0146Mr.名無しさん
垢版 |
2018/10/11(木) 13:09:23.80
お天気表示ソフトが3時間おきに天気取得にでかけるんだけど
これを、何時に起動したとしても、1回目の取得のあとは
0:05
3:05
6:05
みたいに3の倍数の時刻の5分後にとりにいくようにコードを書き直そう
0147おれさま ◆6CTEZS59O00a
垢版 |
2018/10/11(木) 13:11:45.62
CalendarのgetInstanceメソッドは、Calendarオブジェクトを返しますが、
このカレンダ・フィールドは現在の日付と時間に初期化されています。

Calendar rightNow = Calendar.getInstance();

現在日時の取得するのにDateクラスのインスタンス生成に頼る必要はない
0148おれさま ◆6CTEZS59O00a
垢版 |
2018/10/11(木) 14:08:14.05
時刻の引き算は一度Dateをlongに変換する

Date d = new Date();
long l = d.getTime();

で変換終わり

getTime()は
CalendarからDateへの変換でも使うし
Dateからlongへの変換でも使うので混同しないように!

ちなみに
CalendarインスタンスのgetTime()、setTime()はともにDateがらみだが
get()、set()はCalendar内部のフィールドがらみメソッド
0150おれさま ◆6CTEZS59O00a
垢版 |
2018/10/11(木) 15:15:03.74
threadについて

MainクラスはRunnableを実装している
Threadインスタンスとしてthrdを宣言して

mainメソッドで
thrd.start();

public void run() {}
の中で
thrd.sleep(1000);

とするとエラーなしで実行はできるものの注意マークがついていて気になっていた
要はstaticの問題

API referenceをみてみると
static void sleep(long millis)
システム・タイマーとスケジューラが正確であることを前提として、
現在実行中のスレッドを、指定されたミリ秒数の間、スリープ(一時的に実行を停止)させます。

となっていてsleep()メソッドはstaticがついている

しかし、staticの基本として、
static宣言されているフィールドやメソッドには
インスタンス変数名で呼び出しても→thrd.sleep();
クラス名で呼び出しても→Thread.sleep();
どちらでもOKなはず
(スッキリ入門367,368ページ)

なぜクラス名が推奨されるのかはよく分からないが
すくなくともクラス名を使うと注意マークが消えることはわかった
0151おれさま ◆6CTEZS59O00a
垢版 |
2018/10/11(木) 15:28:59.05
おまけだが
static関連で制限される事項として

staticがついているメソッド内でフィールドやメソッドを使う時は
そのフィールドやメソッドはstaticでなければならない

つまり>>150の例で言えば、sleep()にstaticがついているから
sleep()の中でフィールドやメソッドを使う時は・・・・
ということになる

が、sleep()はおれが作ったものじゃないから制限されるといわれても困るわけで
今回の問題とは無関係
0152おれさま ◆6CTEZS59O00a
垢版 |
2018/10/11(木) 15:44:05.19
おれのプログラムだとメインのクラスが

public class Main extends JFrame implements Runnable {}

と宣言されていて、MainにRunnableを実装している
なので、Mainクラスのなかにpublic void run()をオーバーロードする目的で設置することになる

もし1つではなく2つスレッドを作りたい時は
MainにRunnableを実装するのではなく

スレッド用に2つ新しいクラスを作って、これらがRunnableを実装する(またはThreadを継承)
それぞれのクラスの中にpublic void run()をおいて処理内容を書いていくとわかりやすいかな
0154Mr.名無しさん
垢版 |
2018/10/12(金) 04:53:03.08
今どきjavaでGUIって笑
そもそもWindowsアプリなら.NET使えよ

ちなみに俺はプログラミング始めて1年ほどだが、PythonのBeautifulSoupでスクレイピングした株価データをMongoDBに永続化し、javaのspringbootで指定された統計データを公開するWEBアプリをVPS上で運用してるから、そこら辺の質問あったらアドバイスしてやるよ
0155Mr.名無しさん
垢版 |
2018/10/12(金) 04:56:31.10
ちなphp(&laravel)とjavascriptも基本的なことならわかるから質問あったらどーぞ
0156Mr.名無しさん
垢版 |
2018/10/12(金) 05:48:39.33
>>152ってどういうこと?
MainクラスがJFrameを継承してRunnableを実装するなんてあり得ない
設計がおかしすぎる

何を作りたいのか知らんがMVCのよくある設計パターンで、ControllerクラスにRunnableを実装したロジック(model)のインスタンスと、JFrameを継承したインスタンスを生成して、JTextfieldなりにsetすればいいんじゃないのか?

それとsleepがstatic云々言ってるが引数がプリミティブ型なんだから、何の関係もない
ちゃんとリファレンス読んだ?
0157おれさま ◆6CTEZS59O00a
垢版 |
2018/10/12(金) 13:51:28.32
まぁまぁ落ち着いて。
基礎的な動きを確認しながらプログラミング練習してる段階なんでね
これはこうしなければならないみたいなものより
これはこうしても動くし、こうやっても動くみたいな知識が面白いんだよ

javaでGUIってwなんていうけど
メーヴェを作って空を飛ぼうとしてるひとに向かって
空飛ぶならヘリコプターかセスナ使えよ!って言ってるのと同じだよ
ゴールに到達するまでの時間を競うつもりもないし。
プログラミングを仕事にしたらそういう世界になっていくんだろうけど
それってつまんないだろうなと思うんだ
せっかく面白い道具があるのに使い方を縛られるなんてね

>>156
どういうレベルから助言をくれてるのかわからないからどう答えるべきなのか迷うんだけど
まず問題なく動いているということが大事で
今作ったものを土台にいろいろ考えていけるといいなと思ってるよ

https://www.javadrive.jp/tutorial/jframe/index5.html
extends JFrame にかんしてはこれ

>ただし、上記のようにした場合、mainメソッドが含まれるSampleクラスは
>単にmainメソッドが存在するだけのクラスとなってしまいます。その為、
>通常はmainメソッドが含まれるクラスそのものをJFrameクラスの
>サブクラスにする方法が取られます。

このサイトではクラス名はSampleだけど、おれのだとMainのままになってるだけ。
おれはね、これ読んだ瞬間に面白いなぁって思ったんだけど。
自分とこのクラスにextendsして自分とこのmainメソッドで自分のインスタンス生成するとかさ
Swingではこれ普通なの?面白いじゃん
じゃ俺もこれ使おうと思ったんだけどね。
基礎レベルのおれには継承やら実装やらの感覚掴むのに悪くないなって思ってる
ちなみにイベント系のインターフェースも全部Mainに実装させたらMainの行があほみたいに長くなったね
今は匿名クラス使ってるけどね

Runnableも同じようなもんだよ

で、あとsleepか
そもそも起きた問題と何をしたら解決したのかがちゃんとそっちに伝わってるかわからないし
何を問題と捉えて助言をくれているのかもわからないからちょっと難しいよ

もし助言くれるなら、なぜthrd.sleep()だと注意マークがでてThread.sleep()だと出ないのかに
焦点を絞ったもので。引数がどうのこうのの話はそもそもそこが問題の原因ではないだろうと
目星を付けて適当に書いただけで。
問題にしているのはsleepの引数ではなくて、
sleepメソッドがインスタンスから呼び出される場合と
クラスから呼び出される場合の違いなんだ

だれかに何かを伝えるためにここに書いているというよりも
自分が見直した時に参考になる程度にしか書いてないから
いろいろ誤解を与えてるようですまんね

このときはこういう風に考えてたけど、間違ってたなとか、
逆に大事な事忘れてたなとか、あとで見たら面白そうじゃん

>>153
( ^ー゚)b
0158おれさま ◆6CTEZS59O00a
垢版 |
2018/10/12(金) 15:00:32.61
ツールチップで次回取得予定の時刻表示させようとしたけど
右クリメニューとかち合うみたいなんでやめやめ
右クリメニューに表示させるかな
いずれにしてもRun()メソッドがらみなんでちょいめんどくさそう
こんなことやる前に、これまでまとめ上げた内容でもう一度作り直してスッキリさせたほうがいいかもしれん
右クリメニュー関連のコードが迷走してるし
0159おれさま ◆6CTEZS59O00a
垢版 |
2018/10/12(金) 15:04:13.11
あとあれだなぁ
ScheduledExecutorServiceを習得したいね
めんどくさそうだったから、一番簡単な処理方法に逃げてきたんで
0160おれさま ◆6CTEZS59O00a
垢版 |
2018/10/13(土) 05:31:12.81
お天気取得ソフトのエラーがたまに起きるので修正
0時回って5分後に取得しようとすると明日の日付がhtml上にまだ表示されてないようだ
このへん適当にコード書いたんで
日付がないときの分岐処理がなかった
String.containsみたいな処理書くときは忘れないようにしないとな
分岐させないと常にエラーがでるようなものだとすぐに気づくんだけど
たまにしかエラーがでないものだと忘れ去ってしまう

表示されたエラーの内容は半分忘れてしまったんだけど
Stringの配列要素番号として -1 が返されてた
明日の日付が見当たらないと -1 を返してくるようだ
0161おれさま ◆6CTEZS59O00a
垢版 |
2018/10/13(土) 05:59:39.35
いやいや違う

>>160修正
containsは分岐処理でかくものだ
エラーの原因はindexOf()で起きてる
indexOfに渡す引数が見当たらない時にエラーだ
0162おれさま ◆6CTEZS59O00a
垢版 |
2018/10/13(土) 10:54:27.87
ウィンドウのD&D移動で、
MouseListenerの
public void mousePressed(MouseEvent e)での処理なんだけど
いつも間違えるのは、コンポーネントの中での相対座標を取得するコード
JFrameを継承するクラス内だからComponentのメソッドで「も」ある
getX()やgetY()を前置きなしにそのまま使えるんだけど
ComponentのメソッドとしてのgetX()、getY()は相対座標取得のメソッドではない

getX()
コンポーネントの原点の現在のx座標を返します。

なんとなく掴みづらい表現なのだがコンポーネントの左上端の絶対座標を意味してる(と思う)

x = getX(); はダメ。ウィンドウ左上端の絶対座標をとってきてしまう
x = e.getX(); が正解。eを生んだコンポーネントであるJFrameの左上端を原点としたマウスプレス点の座標を取得できる

>>120では、この辺の処理は
pt = e.getPoint();
をつかっており、x と y をばらばらに取得していない
ばらばらに取得するならここで書いたように e.getX()、 e.getY() を使うことになる
0163おれさま ◆6CTEZS59O00a
垢版 |
2018/10/13(土) 15:07:40.61
package privateのクラスをよく使うんだけど
スッキリ入門のどこに書いてあったか探し出せなかったんだけど
やっとみつかったわ
カプセル化のところだ
0165おれさま ◆6CTEZS59O00a
垢版 |
2018/10/14(日) 06:03:39.80
タイトルなしのウィンドウを作り
D&D移動・右クリから閉じる・前回開いた場所で開き直す

こんだけはそらで書けるようにした
いろんな要素が含まれてるから基本覚えるには役に立つ
特にイベント処理は
ActionListener
MouseListener
MouseMotionListener
WindowListener
ComponentListener
が含まれていて練習としては悪くない
Propertyファイルの取り扱いも基礎レベルでしかないけど
しっかり覚えたんで今後に使えそう

またテキストに戻るか
■ このスレッドは過去ログ倉庫に格納されています

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