オブジェクトをファイルに保存するときにJTableとSerializableまたはJavaのテーブルとタンバリンと踊る

はじめに



デザイナーとして、私はプログラムを書くことの始まりのいずれかの実装に創造性の余地を必要とすることがたまたま起こりました。 クロスプラットフォームソフトウェアを常に夢見ていたので、長い間、Javaなどのプラットフォームに注目していました。 そして最近、私はJTableのようなJavaのクールなコンポーネントをマスターすることに決めました。これは、プログラムでテーブルを使用することが常に好きだったためです。



一般に、私は難しいことではありません-オブジェクトとしてファイルに保存できるテーブルを作成し、同時にエラーを強調表示することで入力されたユーザー入力を追跡し、テーブルの最も重要な要素を強調表示することでプログラムのテーブルとの通信を簡素化します。 私はコードを書くときの段階的なデバッグの原則によるプログラミングの支持者なので、インターネット上で安定したコードの既製の部分の可用性は私にとって非常に重要でした...しかし...徹底的な検索の後、それは実験的に確立されました インターネットでは、より多くの、またはより良いコードを取得するための通常のソースは数個しかありません。



いいえ、いいえ、私はあなたをここに送りません(javatalks.ruなどのユーザーからの人気の引用-「愚かな質問をする前に、 ここを見てください ...」)。



そしてここ 。 (テーブルの使用方法-チュートリアル)



またはこちら (Swingコンポーネントの使用:例)。



またはテーブルの標準ヘルプ



しかし、これは簡単ではないと言いますが、私はそこを見て、知覚と理解可能な作業コードの存在の両方でJavaドックが少し時代遅れであることを認識しました(Javaバージョン7.01を使用しました)。 それでも、これらの参考資料を読まなければ、Javaテーブルの本質、論理、心理を理解することはできません。



このため、以下で説明するJTableテーブルのシリアル化の安定した例は、自分が何をしていて何を取得したいかを理解している場合にのみ、希望どおりに機能します。 最後に追加します-いくつかのコードはさまざまなリソースでインターネット上で収集されました(それらすべてに感謝します)が、それらはすべて1つの共通点を持っています-私はそれらをデバッグし、私のプログラムにこすりました、つまり、私は完全に機能するコードを見つけませんでした。 でも... コードを作成したのは、シリアル化プログラムの作業コードを英語のリソースの1つから取得したためです。テーブルのデータを変更しようとするとクラッシュしました(残念ながらリソースへのリンクは失われました)...

しかし、「ドラゴンについて」のコードは順番に。



おおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお



さて、今が私に言う時です。「タンバリンと踊っていますか? またはそれを読んいないのですか? Googleの方が優れており、設計のためにすべての頭脳を急上昇させないでください。それなしではできません。「実際、この本の翻訳を読んだ後」Java 2. Volume 2.プログラミングの微妙さ。 著者-ケイ・ホルストマンとハリー・コーネル「(私は8版目の印刷版を持っています)、素晴らしいコードを見つけました:



//   FileOutputStream fos = new FileOutputStream("temp.out"); ObjectOutputStream oos = new ObjectOutputStream(fos); SerialTest st = new SerialTest(); oos.writeObject(st); oos.flush(); oos.close(); //   FileInputStream fis = new FileInputStream("temp.out"); ObjectInputStream oin = new ObjectInputStream(fis); TestSerial ts = (TestSerial) oin.readObject(); System.out.println("version="+ts.version);
      
      







誰も、私が魔法のマントラを「実装可能な直列化可能」とするところならどこでも、テーブルを使いたいと思っていました。



-はい、別個のクラスを実装するのではなく、TableCellRendererを動的に作成し、その中で必要なことをすべて行うと、すぐにJTableでタリーになります! -彼らは一人で言った...



-いや... Javaは "khukh-mukhra"ではなく、MVCモデルをキャンセルした人はいないため、別のクラスが必要です。 -他の人が言った。



一般に、機能しないか部分的に機能しないクラスとメソッドの実装に関するこれらの論争と提案はすべて非常に怒っており、すべてに唾を吐き、デフォルトの「灰色」グラフィカルインターフェースでテーブルを作成したかった...突然、外国のフォーラムの1つで、著者によると、100%動作していて、デザイナーの気まぐれに合うコードを見つけました。 このコードを注意深く調べた結果、ファイルがディスクにない場合にテーブルテンプレートを作成し、テーブルを埋める方法を見つけました。 コードを確認した後(上記に非常に近い)、私はそれが機能することを発見して驚きました! 「ああ、天国だ!」-私は思った-「私の祈りに答えて、タンバリンを私の娘に返してくれませんか?!」...しかし、テーブルにデータを入力し、保存ボタンをクリックするとすぐに...



今、それは名誉の問題となっています! タンバリンの絶え間ない音のために、私の娘のタンバリンの有無や隣人の神経衰弱にマントラムが影響を与えることは許されませんでした...要するに、テーブルのハイライトとの短い戦いの後:



 // ,    table.clearSelection();
      
      







私は全世界のシャーマンとクリエーター自身にアピールすることに決めました...そして、Oracleバグトラッカーに行きましたが、これは間違いだと気づいたのです。



そして、Javaバージョン「1.4.0-beta2」から、長年にわたって戦いが続いています。



それから私は、クレオパトラのような特に賢明なシャーマンがずっと前に単純な呼び出しでエラーログドラゴンの翼を切り落としていたことを見ました:



 //   ,       //     "",         table.editingStopped(null); // ,    Java,    /*: * * The first issue in the description deals with the improper behavior * of losing edits on focus exit the first time but for not subsequent * attempts. The problem was correctly diagnosed by Kleopatra in bug * report 4518907. java.swing.JTable indeed does need to set 'editorRemover' * to null after calls to * removePropertyChangeListener("focusOwner", editorRemover); * in both removeNotify() and in removeEditor(). * */ //      ,      table.removeEditor(); //         table.removeNotify();
      
      







まあ、それは、ドラゴンが敗北しているようだ...

しかし、いや、彼はTableCellRendererでクラスに移動しました...



レッスンを描く、または「いいえ、いいえ、エラーのある行を強調表示する必要があります」



通常のテーブルの視覚化エラーで燃え上がった新しいキャンプファイヤーでの複雑なダンスの後、セルとカラム名(ラベル)の2つのクラスのテーブルレンダリングを実装することが適切であることがわかりました。



 //   class JCTableCellRenderer extends JLabel implements TableCellRenderer, Serializable {} //    class JColumnRenderer extends JLabel implements TableCellRenderer, Serializable {}
      
      







これをすべて宣言する必要があります。



 //      JCTableCellRenderer table.setDefaultRenderer(Object.class, new JCTableCellRenderer());
      
      







loadColumn()メソッドの最初に、次のように記述します。



 //   JColumnRenderer   TableColumn //   JCTableCellRenderer, -        TableCellRenderer renderer = new JColumnRenderer();
      
      







すべてがすぐに適切に配置され、すべてのデータが完全に読み取られてレンダリングされました。

今、私は本当に必要なものをインターネットで検索し始め、セル、行、列を描き始めました。

奇妙なことに、しかし、私が必要としたものと正確に一致するすべてのリンクがここに導かれました



情報は非常に貴重ですが、デザインは少なく、TableCellRendererについてはほとんど言われていません。 自分でテーブルを色付けするさまざまな方法を試し始めましたが、最終的に何を学びましたか?



 //   public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {...} //     : //@param: table -      , ,  //@param: value -        //@param: isSelected -      (   ) //@param: hasFocus -      //@param: row -        //@param: column -       
      
      







JTableテーブルの色付けの例:



 //     JLabel,     , -  JLabel c = new JLabel(value.toString()); //    ,       - value.toString() //      "jpg",     if(value.equals("jpg")){c.setOpaque(true);c.setBackground(new Color(152, 251, 152));} //        if(column==0){c.setOpaque(true);c.setBackground(new Color(255, 248, 220));} //       ,         "iff" if(table.getValueAt(row, 7).equals("iff")){ c.setOpaque(true); c.setBackground(new Color(255, 105, 180)); c.setForeground(Color.white);} //    :   ,         //...               //,    : (String)table.getModel().getValueAt(row, 4) //    int a = Integer.parseInt(""+table.getModel().getValueAt(row, 4)); int b = Integer.parseInt(""+table.getModel().getValueAt(row, 5)); if(a > b) { c.setOpaque(true);c.setBackground(Color.red);c.setForeground(Color.yellow); if(column==8) { c.setText("Error this value: colomn - \"Start\", row - " + (row+1)); table.getModel().setValueAt(c.getText(), row, column); } } else { //   ,      ,      //     ,     //,  ,           //       if(column==8) { java.io.File f = new java.io.File((String) table.getModel().getValueAt(row, 9)); if(f.exists()) { table.getModel().setValueAt("<This file is exist>", row, column); } else { table.getModel().setValueAt("<This file is not exist!!!>", row, column); c.setOpaque(true);c.setBackground(Color.red);c.setForeground(Color.yellow); } } } //     http://skipy-ru.livejournal.com/1577.html //  -         // using L&F colors if(isSelected) { c.setOpaque(true); c.setForeground(isSelected ? UIManager.getColor("Table.selectionForeground") : UIManager.getColor("Table.foreground")); c.setBackground(isSelected ? UIManager.getColor("Table.selectionBackground") : UIManager.getColor("Table.background")); c.setBorder(hasFocus ? BorderFactory.createLineBorder(UIManager.getColor("Table.selectionForeground"), 1) : BorderFactory.createEmptyBorder(2, 2, 2, 2)); // ,           //       if(value.equals("jpg")){c.setOpaque(true);c.setBackground(new Color(0, 128, 128));} if(value.equals("png")){c.setOpaque(true);c.setBackground(new Color(250, 250, 210));} if(value.equals("iff")){c.setOpaque(true);c.setBackground(new Color(72, 61, 139));c.setForeground(Color.white);} if(column==0){c.setOpaque(true);c.setBackground(new Color(210, 105, 30));} }
      
      







まあ、それがすべてです。



これですべてが機能します-ファイルに保存され、希望の色でペイントされます。

計画を実装するために、Eclipse v開発環境を使用しました。 3.7



画像



さて...この場所を読んでくれたら、お時間をいただきありがとうございます。

「データベースでこれを行うにはどうすればよいですか?」または「JCTableCellRendererクラスの値をチェックするときにforループを実装すると、テーブルがひどくハングする」などの質問をしたい場合は、データベースに上記のコードがあることを追加します私は適用しませんでした(しかし、何らかの理由で安定して動作することを確信しています)。また、描画クラスに実装されたループは、Flashのクリップタイムラインのタイマーと同じ問題です。 「より単純で、より高速」という原則に従ってコードを常に最適化することをお勧めします。



プログラム自体の必要な外部クラスとコードが添付されています(Eclipseで開きます)。



皆さん、頑張ってください。



All Articles