JFreeChartのサンプル
参考(ほぼコピペ)
http://kamifuji.dyndns.org/JSupport/JAVA_JFreeChart/BarChart/index.html
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;
import javax.swing.*;
import java.awt.*;
public class JfcTraning extends JFrame {
public static void main(String[] args){
JfcTraning frame = new JfcTraning();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(10,10,500,500);
frame.setTitle("Sample Graph");
frame.setVisible(true);
}
JfcTraning(){
DefaultCategoryDataset datas = createData();
JFreeChart chart = ChartFactory.createLineChart("輸入量", "年度", "トン(t)",
datas, PlotOrientation.VERTICAL,true,false,false);
ChartPanel cPanel = new ChartPanel(chart);
getContentPane().add(cPanel, BorderLayout.CENTER);
}
private DefaultCategoryDataset createData(){
DefaultCategoryDataset datas = new DefaultCategoryDataset();
datas.addValue(300,"Canada","2010/1");
datas.addValue(500,"Canada","2010/2");
datas.addValue(null,"Canada","2010/3");
datas.addValue(120,"Canada","2010/4");
datas.addValue(240,"Canada","2010/5");
datas.addValue(150,"UK","2010/1");
datas.addValue(700,"UK","2010/2");
datas.addValue(200,"UK","2010/3");
datas.addValue(300,"UK","2010/4");
datas.addValue(100,"UK","2010/5");
return datas;
}
}
JSpinner(NumberFormat)の初期値をnullにする(見た目だけ)
目標
画面にJSpinnerが配置されているとする. このとき,初期値が入っていない状態にしたい.
コードサンプル
public class SpinnerGui extends JDialog{ public static void main(String[] args) { SpinnerGui frame = new SpinnerGui(); frame.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); frame.setBounds(10,10,300,200); frame.setTitle("すぴなー"); frame.setVisible(true); } public SpinnerGui() { final JSpinner spinner = new JSpinner(new SpinnerNumberModel(0,0,10,1)); final JTextField spinnerTF = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField(); final Color spinnerForeground = spinnerTF.getForeground(); final Color spinnerBackground = spinnerTF.getBackground(); spinnerTF.setColumns(5); spinner.addChangeListener(new ChangeListener(){ public void stateChanged(ChangeEvent ce){ if(((Integer)spinner.getValue()).intValue() == 0){ spinnerTF.setForeground(spinnerBackground); } else spinnerTF.setForeground(spinnerForeground); } }); spinnerTF.setForeground(spinnerBackground); JPanel p = new JPanel(); p.add(spinner); getContentPane().add(p,BorderLayout.CENTER); } }
だいたい,このページの中身通り.先人に感謝
Is it possible for a JSpinner to show no default value? (Swing / AWT / SWT forum at Coderanch)
Listから,親子関係のあるJTreeを作る
結論を言ってしまうと,TreeNodeをimplementsするのが早い.
間違っても,DefaultMutableTreeNodeだけで何とかしようとなんて思わないこと(3敗).
1.TreeNodeの実装クラス
import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Objects; import javax.swing.tree.TreeNode; public class MyTreeNode implements TreeNode{ private String id; private MyTreeNode parent; private String parentName; private String indivisual; private List<MyTreeNode> children = new ArrayList<>(); public MyTreeNode(String code, String indivisual, String parent) { this.id = code; this.indivisual = indivisual; this.parentName = parent; } @Override public TreeNode getChildAt(int childIndex) { return children.get(childIndex); } @Override public int getChildCount() { return children.size(); } @Override public TreeNode getParent() { if(Objects.nonNull(parent)){ return this.parent; }else { return null; } } @Override public int getIndex(TreeNode node) { // TODO 自動生成されたメソッド・スタブ return 0; } @Override public boolean getAllowsChildren() { return true; } @Override public boolean isLeaf() { if(Objects.isNull(children)) { return true; }else { return false; } } @Override public Enumeration children() { return Collections.enumeration(this.children); } @Override public String toString() { return this.indivisual; } public void add(MyTreeNode futureChild) { // if(this.getChildCount()>0) { for(MyTreeNode node: this.children) { System.out.println(node.indivisual); if(node.indivisual.equals(futureChild.parentName)) { node.add(futureChild); } } } //直属の子として追加 if(this.indivisual.equals(futureChild.parentName)) { this.children.add(futureChild); } } }
2. データとツリー作成部分
import java.awt.BorderLayout; import java.awt.Dimension; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTree; public class MyTree extends JFrame { public static void main(String[] args){ //List部分 List<TreeObject> toList = new ArrayList<>(); toList.add(new TreeObject("10", "root","GG")); toList.add(new TreeObject("20", "root","BB")); toList.add(new TreeObject("11", "GG", "Sol")); toList.add(new TreeObject("12", "GG", "Ky")); toList.add(new TreeObject("13", "GG", "Diz")); toList.add(new TreeObject("21", "BB", "Jin")); toList.add(new TreeObject("22", "BB", "Es")); MyTree frame = new MyTree(toList); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(10, 10, 300, 200); frame.setTitle("タイトル"); frame.setVisible(true); } public MyTree(List<TreeObject> toList) { MyTreeNode top = new MyTreeNode("00", "root", ""); for(TreeObject item: toList ) { top.add(new MyTreeNode(item.getCode(), item.getIndividual(), item.getParent())); } //い つ も の JTree tree = new JTree(top); JScrollPane scrollPane = new JScrollPane(); scrollPane.getViewport().setView(tree); scrollPane.setPreferredSize(new Dimension(280, 180)); JPanel p = new JPanel(); p.add(scrollPane); getContentPane().add(p, BorderLayout.CENTER); } }
3. 感想
自分がプログラマーじゃないんだなーと思った.
まあ,続けるんですけどね?この仕事.楽しくはあるので.
頑張ってサニタイズする
サニタイズじゃなくて,バリデートともいうらしい. 相変わらず未完.
public class SqlSanitizer { public static String spaceReplacer(String sentence) { String after = sentence.replace(" ", ","); after = after.replace(" ",","); return after; } public static String[] splitParser(String sentence) { String after = sentence.replaceAll(",+", ","); return after.split(","); } public static boolean kakkoChecker(String[] sentence) { int sCounter = 0; int eCounter = 0; for(String s: sentence) { if(s.equals("(")) sCounter++; if(s.equals(")")) eCounter++; } return sCounter == eCounter ? true:false; } }
ローカルのJsonファイルを読み込む(JSonic利用)
Jsonicっていう,JavaでJsonを扱うライブラリを利用することになりました.
相変わらず,分からない.ので調べた.
1.利用するデータ
{ "x1":["Indigo","3"], "x2":["Rot","2"] }
2.取り込み用クラス
json側のキー名と,フィールドのプロパティ名が一致していることが味噌.
public class ListData { private String[] x1; private String[] x2; public String[] getX1() { return x1; } public void setX1(String[] x1) { this.x1 = x1; } public String[] getX2() { return x2; } public void setX2(String[] x2) { this.x2 = x2; } }
3.Json取得クラス
今回は,Mapとして調理します.迫真のクソコード
public class JsonPractice { private String filepath = "テキトーなファイルパス\\setjson.json"; public Map getList() { FileInputStream fis; try { fis = new FileInputStream(filepath); Map ldata = (Map)JSON.decode(fis); return ldata; } catch (FileNotFoundException e) { e.printStackTrace(); return null; } catch (JSONException e) { e.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); return null; } } }
4.結果
うまくとれてるっぽいですよ?
class JsonPracticeTest { @Test public void TestGetListdata() { JsonPractice jsp = new JsonPractice(); Map<String,List<String>> ldata = jsp.getList(); List<String> x1 = ldata.get("x1"); assertThat(x1.get(0), is("Indigo")); } }
もっと楽なjsonの扱い方ないんだろうか? 調べが雑なのは認める...
JComboBoxの状態に応じて,JPanelの中身を切り替える
やりたいことはタイトル通り
コードの解説的なものは,いつか書く
あと,割とクソコード
あと,コード間違ってる気がする(なら公開するな)
コードそのもの
public class PanelPractice extends JFrame{ public static void main(String[] args) { PanelPractice frame = new PanelPractice(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(10, 10, 300, 100); frame.setTitle("タイトル"); frame.setVisible(true); } private JTextField txt = new JTextField(3); private JComboBox comb2 = new JComboBox<String>(); PanelPractice(){ JButton button1 = new JButton("Button1"); JButton button2 = new JButton("Button2"); JButton button3 = new JButton("Button3"); JPanel p = new JPanel(); p.setLayout(new GridLayout()); JPanel vpanel = new JPanel(); vpanel.add(txt); //JCombo String[] data = {"Ky","Sol"}; JComboBox cmb = new JComboBox<String>(data); cmb.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String selectedItem = (String)cmb.getSelectedItem(); Runnable changeComp = new Runnable() { @Override public void run() { if(Objects.isNull(selectedItem)) { return; }else if(selectedItem.equals("Ky")) { vpanel.remove(comb2); vpanel.add(txt); vpanel.validate(); pack(); }else { vpanel.removeAll(); vpanel.add(comb2); vpanel.validate(); pack(); } } }; SwingUtilities.invokeLater(changeComp); } }); cmb.setSelectedItem(null); p.add(cmb); p.add(vpanel); p.add(button3); getContentPane().add(p, BorderLayout.CENTER); } }
(投稿した1分後に,修正部分見つかったよ・・・)
Java Swingで,値検査(年月日)とフル桁遷移を実現する
業務でJava Swingを利用することになったんですが・・・.しらねえ. 基本的なことはググれば分かるんですが,タイトルのネタ二つがよくわからなかったので,調べてみた
1.値検査(年月日)
一言でいうと,JFormattedTextFieldっていうコンポーネントを使い,そのコンポーネントにDocumentListener()っていうリスナーを刺せばOK. JFormattedTextFieldは,引数として渡されたフォーマット形式(SimpleDateFormatとか)どおりに,書式を整えてくれるもの. DocumentLisnerは,テキストフィールドの変化(入力・削除など)に対するリスナー.
以下,具体的なコード.オリジナルのコードから,必要な部分を切り取っただけなので,動かないかも.
public class HavingDataChecker extends JFrame{ private JFormattedTextField text1; public static void main(String[] args) { HavingDataChecker frame = new HavingDataChecker(); //set close event frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //set window title frame.setTitle("JFormattedTextField Sample"); //set frame coordinaiton frame.setBounds(100,200,450,250); //visible frame frame.setVisible(true); } public HavingDataChecker() { JPanel panelBase = new JPanel(); //define format SimpleDateFormat nf1 = new SimpleDateFormat("MM"); //create textfield text1 = new JFormattedTextField(nf1); //add listener to textfield text1.getDocument().addDocumentListener(new DocumentListener() { @Override public void removeUpdate(DocumentEvent e) { // TODO 自動生成されたメソッド・スタブ checkMonth(text1); } @Override public void insertUpdate(DocumentEvent e) { // TODO 自動生成されたメソッド・スタブ checkMonth(text1); } @Override public void changedUpdate(DocumentEvent e) { // TODO 自動生成されたメソッド・スタブ checkMonth(text1); } }); //set item size text1.setPreferredSize(new Dimension(180,20)); //add textfield to panel panelBase.add(text1); //add panel getContentPane().add(panelBase); } private void checkMonth(JTextField from) { Runnable docheck = new Runnable() { @Override public void run() { // TODO 自動生成されたメソッド・スタブ String insertedString = from.getText(); if(!(insertedString.equals(""))) { int value = Integer.parseInt(insertedString); if(value > 12) { from.setText(""); } } } }; SwingUtilities.invokeLater(docheck); } }
重要なのはこの辺
1-1. JFormattedTextField作成部分
//define format SimpleDateFormat nf1 = new SimpleDateFormat("MM月"); //create textfield text1 = new JFormattedTextField(nf1);
上の方で,書式(この場合は,年月日の「月」部分)を指定している. 下の部分で,JFormattedTextFieldを作成する.
1-2. 値検査
DocumentListenerの刺し方はこんな感じ.
//add listener to textfield text1.getDocument().addDocumentListener(new DocumentListener() { @Override public void removeUpdate(DocumentEvent e) { // TODO 自動生成されたメソッド・スタブ checkMonth(text1); } @Override public void insertUpdate(DocumentEvent e) { // TODO 自動生成されたメソッド・スタブ checkMonth(text1); } @Override public void changedUpdate(DocumentEvent e) { // TODO 自動生成されたメソッド・スタブ checkMonth(text1); } });
今回は,「月」の型検査をやりたい.なので,「13」以上の値が入力されたら,空文字に置換する. ただ,EDTの関係があるので,処理はRunnableインタフェースを実装しなければいけない.
private void checkMonth(JTextField from) { Runnable docheck = new Runnable() { @Override public void run() { // TODO 自動生成されたメソッド・スタブ String insertedString = from.getText(); if(!(insertedString.equals(""))) { int value = Integer.parseInt(insertedString); if(value > 12) { from.setText(""); } } } }; SwingUtilities.invokeLater(docheck); }
(「0月」を許容しているのはご愛嬌・・・.サンプルコードだから・・・)
2.フル桁遷移
年月日の「年」を入れたら,「月」のテキストフィールドに自動的に移動するやつのこと. 実装方法は, めっちゃ簡単.JTextField.getCaretPosition() っていうのを使えば,「現在のカーソル位置」を取得できる.何らかのリスナーを実行した後に,この値を取得すればいい. 移動先のテキストフィールドの指定は,JTextField.requestFocus()でOK. 私は,こんなコードにまとめた.遷移元と遷移先を指定する感じ.
private void goNext(JTextField from, JTextField to) { if(from.getCaretPosition() == 1) {to.requestFocus();}; }
とりあえず,こんな感じでおわり.
3. 既知の問題点
所定の値以外が入力された後の値がへん
例えば「13」っていれると,強制的に「12」が入る. 空文字を入れたはずなのに・・・
SimpleDateFormat("MM") をSimpleDateFormat("DD")に変えた後に, 「31」とかを入力すると, 「31」が入力されるので,SimpleDateFormatまたはJFormattedTextField側の問題だと推測している. 調べなきゃ・・・.
例外処理をしていないので「あああ」とかを入れると,実行時エラーが出る
NumberFormatException(?)が出ます.まじめに制御すればいいので,致命傷ではない(と思っている). いつか,解決版に更新するかも.