Kotlin のバックアップソース(No.12)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- バックアップ を表示
- Kotlin へ行く。
- 1 (2017-05-31 (水) 18:35:21)
- 2 (2017-05-31 (水) 19:53:14)
- 3 (2017-05-31 (水) 20:59:47)
- 4 (2017-05-31 (水) 23:55:03)
- 5 (2017-06-01 (木) 10:59:15)
- 6 (2017-06-01 (木) 12:23:00)
- 7 (2017-06-01 (木) 16:03:15)
- 8 (2017-06-01 (木) 17:20:46)
- 9 (2017-06-04 (日) 13:23:23)
- 10 (2017-06-05 (月) 18:47:29)
- 11 (2017-06-08 (木) 14:12:31)
- 12 (2017-06-08 (木) 19:03:39)
- 13 (2017-06-13 (火) 14:53:44)
- 14 (2017-06-26 (月) 15:09:29)
- 15 (2017-09-04 (月) 15:51:42)
- 16 (2017-09-04 (月) 17:12:49)
- 17 (2017-10-03 (火) 14:50:20)
- 18 (2017-11-07 (火) 16:44:56)
- 19 (2017-11-08 (水) 16:37:18)
- 20 (2017-11-13 (月) 18:11:40)
- 21 (2017-11-20 (月) 18:51:07)
- 22 (2017-12-12 (火) 19:07:44)
- 23 (2017-12-12 (火) 20:36:03)
- 24 (2017-12-14 (木) 15:57:09)
- 25 (2017-12-15 (金) 20:15:22)
- 26 (2017-12-15 (金) 21:32:06)
- 27 (2017-12-18 (月) 16:30:34)
- 28 (2017-12-23 (土) 15:30:50)
- 29 (2017-12-25 (月) 13:58:48)
- 30 (2017-12-25 (月) 17:40:04)
- 31 (2017-12-25 (月) 20:12:05)
- 32 (2017-12-28 (木) 22:22:38)
- 33 (2018-01-09 (火) 18:02:52)
- 34 (2018-03-02 (金) 18:20:39)
- 35 (2018-03-05 (月) 17:52:19)
- 36 (2018-03-26 (月) 21:25:15)
- 37 (2018-08-09 (木) 18:17:44)
- 38 (2018-10-30 (火) 17:00:35)
- 39 (2018-10-31 (水) 15:46:41)
- 40 (2018-10-31 (水) 17:07:25)
- 41 (2018-11-05 (月) 18:05:10)
- 42 (2018-11-06 (火) 18:51:01)
- 43 (2018-11-07 (水) 13:55:45)
- 44 (2018-11-07 (水) 19:30:57)
- 45 (2018-11-07 (水) 21:39:08)
- 46 (2018-11-08 (木) 13:58:44)
- 47 (2018-11-08 (木) 14:59:11)
- 48 (2018-11-08 (木) 19:22:44)
- 49 (2018-11-09 (金) 17:05:26)
- 50 (2018-11-13 (火) 14:49:29)
- 51 (2018-11-15 (木) 15:36:23)
- 52 (2018-11-16 (金) 18:22:36)
- 53 (2018-12-07 (金) 19:39:18)
- 54 (2018-12-09 (日) 21:57:42)
- 55 (2018-12-10 (月) 16:52:25)
- 56 (2018-12-10 (月) 18:05:19)
- 57 (2018-12-17 (月) 17:23:20)
- 58 (2018-12-20 (木) 13:56:07)
- 59 (2019-01-07 (月) 16:14:59)
- 60 (2019-01-17 (木) 17:40:32)
- 61 (2019-01-18 (金) 19:53:07)
- 62 (2019-02-01 (金) 21:34:36)
- 63 (2019-02-02 (土) 23:27:16)
- 64 (2019-02-12 (火) 16:09:08)
- 65 (2019-02-26 (火) 19:20:13)
- 66 (2019-02-26 (火) 21:11:09)
- 67 (2019-02-27 (水) 15:48:09)
- 68 (2019-02-27 (水) 19:31:05)
- 69 (2019-02-27 (水) 21:18:44)
- 70 (2019-02-28 (木) 22:09:03)
- 71 (2019-03-11 (月) 15:32:26)
- 72 (2019-03-14 (木) 17:38:07)
- 73 (2019-03-25 (月) 19:57:36)
- 74 (2019-03-27 (水) 20:28:44)
- 75 (2019-04-02 (火) 19:32:48)
- 76 (2019-04-04 (木) 20:13:39)
- 77 (2019-04-05 (金) 14:32:20)
- 78 (2019-04-05 (金) 18:05:49)
- 79 (2019-04-09 (火) 16:53:20)
- 80 (2019-04-17 (水) 16:40:32)
- 81 (2019-04-23 (火) 18:47:09)
- 82 (2019-04-23 (火) 20:15:22)
- 83 (2019-04-24 (水) 18:46:55)
- 84 (2019-05-02 (木) 17:57:41)
- 85 (2019-05-20 (月) 19:24:10)
- 86 (2019-05-22 (水) 17:19:10)
- 87 (2019-05-22 (水) 19:35:38)
- 88 (2019-05-23 (木) 17:54:37)
- 89 (2019-05-27 (月) 18:26:22)
- 90 (2019-05-28 (火) 15:22:38)
- 91 (2019-06-10 (月) 19:46:56)
- 92 (2019-06-11 (火) 19:41:28)
- 93 (2019-06-14 (金) 16:18:02)
- 94 (2019-06-14 (金) 20:35:44)
- 95 (2019-06-24 (月) 14:43:23)
- 96 (2019-06-24 (月) 18:26:16)
- 97 (2019-07-02 (火) 16:23:12)
- 98 (2019-07-29 (月) 16:16:17)
- 99 (2019-08-08 (木) 22:52:05)
- 100 (2019-08-13 (火) 17:47:36)
- 101 (2019-08-15 (木) 16:09:14)
- 102 (2019-08-26 (月) 16:39:57)
- 103 (2019-08-26 (月) 18:12:51)
- 104 (2019-08-26 (月) 20:23:07)
- 105 (2019-08-27 (火) 14:22:16)
- 106 (2019-08-28 (水) 19:38:13)
- 107 (2019-08-29 (木) 19:11:00)
- 108 (2019-09-12 (木) 16:08:13)
- 109 (2019-11-12 (火) 19:55:32)
- 110 (2019-11-13 (水) 13:29:33)
- 111 (2019-12-05 (木) 22:21:26)
- 112 (2019-12-16 (月) 17:39:21)
- 113 (2019-12-17 (火) 14:36:42)
- 114 (2020-01-06 (月) 18:30:19)
- 115 (2020-01-16 (木) 20:26:27)
- 116 (2020-03-19 (木) 20:05:04)
- 117 (2020-08-24 (月) 14:44:31)
- 118 (2020-08-26 (水) 12:18:57)
- 119 (2020-11-12 (木) 10:10:09)
- 120 (2021-09-28 (火) 12:56:54)
- 121 (2021-12-13 (月) 15:11:40)
- 122 (2022-03-29 (火) 15:20:50)
- 123 (2023-07-10 (月) 11:14:56)
- 124 (2024-02-21 (水) 02:08:19)
--- keywords: [Kotlin, Swing, Java] description: KotlinでのSwingの使用方法に関するメモなど author: aterai pubdate: 2017-05-31 --- #contents * 概要 [#summary] `Kotlin`で`Swing`を使用する場合のサンプルです。 * 実行環境 [#s42e991c] - [http://sdkman.io/ SDKMAN! the Software Development Kit Manager]で`kotlin`をインストール可能 $ curl -s "https://get.sdkman.io" | bash $ sdk install kotlin $ kotlinc -version info: Kotlin Compiler version 1.1.2-2 $ kotlinc hello.kt -include-runtime -d hello.jar && "$JAVA_HOME/bin/java" -jar hello.jar * Swing + Kotlin サンプル [#swing] ** JTable [#JTable] - メモ -- `Class<?>`は`Class<Any>`か`Class<Object>` -- `Object#getClass()`は`o.javaClass` --- [https://kotlinlang.org/docs/reference/java-interop.html#getclass getClass() - Calling Java from Kotlin - Kotlin Programming Language] --- `Integer::class.java`は`Class<Integer>`になるので、以下のサンプルで使用すると、`error: type inference failed. Expected type mismatch: inferred type is Class<Integer> but Class<Any> was expected`とエラーになる -- オーバーライドの方法、`@Override`は`override` -- 配列、二次元配列 --- [https://kotlinlang.org/docs/reference/java-interop.html#java-arrays Java Arrays - Calling Java from Kotlin - Kotlin Programming Language] -- `apply` #twocolumn `Java` #code{{ import java.awt.*; import javax.swing.*; import javax.swing.table.*; public class JTableExample { public JComponent makeUI() { String[] cn = {"String", "Integer", "Boolean"}; Object[][] data = { {"aaa", 12, true}, {"bbb", 5, false}, {"CCC", 92, true}, {"DDD", 0, false} }; TableModel m = new DefaultTableModel(data, cn) { @Override public Class<?> getColumnClass(int col) { return getValueAt(0, col).getClass(); } }; JTable table = new JTable(m); table.setAutoCreateRowSorter(true); JPanel p = new JPanel(new BorderLayout()); p.add(new JScrollPane(table)); return p; } public static void main(String... args) { EventQueue.invokeLater(() -> { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(new JTableExample().makeUI()); f.setSize(320, 240); f.setLocationRelativeTo(null); f.setVisible(true); }); } } }} #twocolumn `Kotlin` #code{{ import java.awt.* import javax.swing.* import javax.swing.table.* fun makeUI(): JComponent { val cn = arrayOf("String", "Integer", "Boolean") val data = arrayOf( arrayOf("aaa", 12, true), arrayOf("bbb", 5, false), arrayOf("CCC", 92, true), arrayOf("DDD", 0, false)) val m = object: DefaultTableModel(data, cn) { override fun getColumnClass(col: Int): Class<Any> { return getValueAt(0, col).javaClass } } val table = JTable(m).apply { autoCreateRowSorter = true } return JPanel(BorderLayout(5, 5)).apply { add(JScrollPane(table)) } } fun main(args: Array<String>) { EventQueue.invokeLater { JFrame("kotlin swing").apply { defaultCloseOperation = JFrame.EXIT_ON_CLOSE add(makeUI()) size = Dimension(320, 240) setLocationRelativeTo(null) setVisible(true) } } } }} #twocolumn ** JTree [#JTree] #twocolumn `Java` #code{{ import java.awt.*; import java.util.*; import javax.swing.*; public class JTreeExample { public JComponent makeUI() { JTree tree = new JTree(); JButton b1 = new JButton("expand"); b1.addActionListener(e -> expandAll(tree)); JButton b2 = new JButton("collapse"); b2.addActionListener(e -> collapseAll(tree)); JPanel pp = new JPanel(new GridLayout(1, 0, 5, 5)); Arrays.asList(b1, b2).forEach(pp::add); JPanel p = new JPanel(new BorderLayout(5, 5)); p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); p.add(new JScrollPane(tree)); p.add(pp, BorderLayout.SOUTH); return p; } protected static void expandAll(JTree tree) { int row = 0; while (row < tree.getRowCount()) { tree.expandRow(row); row++; } } protected static void collapseAll(JTree tree) { int row = tree.getRowCount() - 1; while (row >= 0) { tree.collapseRow(row); row--; } } public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(new JTreeExample().makeUI()); f.setSize(320, 240); f.setLocationRelativeTo(null); f.setVisible(true); }); } } }} #twocolumn `Kotlin` #code{{ import java.awt.* import javax.swing.* fun makeUI(): JComponent { val tree = JTree() val p = JPanel(GridLayout(1, 0, 5, 5)).apply { add(JButton("expand").apply { addActionListener { expandAll(tree) } }) add(JButton("collapse").apply { addActionListener { collapseAll(tree) } }) } return JPanel(BorderLayout(5, 5)).apply { setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)) add(JScrollPane(tree)) add(p, BorderLayout.SOUTH) } } fun expandAll(tree: JTree) { var row = 0 while (row < tree.getRowCount()) { tree.expandRow(row) row++ } } fun collapseAll(tree : JTree) { var row = tree.getRowCount() - 1 while (row >= 0) { tree.collapseRow(row) row-- } } fun main(args: Array<String>) { EventQueue.invokeLater { JFrame("kotlin swing").apply { defaultCloseOperation = JFrame.EXIT_ON_CLOSE add(makeUI()) size = Dimension(320, 240) setLocationRelativeTo(null) setVisible(true) } } } }} #twocolumn ** JCheckBox [#JCheckBox] - `Smart Cast`、キャストで`if`のネストが深くなるのを避けたい -- 以下のような場合は、`apply`で回避できる #twocolumn `Java` #code{{ import java.awt.*; import javax.swing.*; public class JCheckBoxExample { public JComponent makeUI() { JCheckBox cb = new JCheckBox("Always On Top", true); cb.addActionListener(e -> { AbstractButton b = (AbstractButton) e.getSource(); Container c = b.getTopLevelAncestor(); if (c instanceof Window) { ((Window) c).setAlwaysOnTop(b.isSelected()); } }); JPanel p = new JPanel(new BorderLayout()); p.add(cb, BorderLayout.NORTH); return p; } public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(new JCheckBoxExample().makeUI()); f.setSize(320, 240); f.setLocationRelativeTo(null); f.setVisible(true); }); } } }} #twocolumn `Kotlin` #code{{ import java.awt.* import javax.swing.* fun makeUI(): JComponent { val cb = JCheckBox("Always On Top", true).apply { addActionListener { val w = getTopLevelAncestor() if (w is Window) { w.setAlwaysOnTop(isSelected()) } } // addActionListener { e -> // val c = e.getSource() // if (c is AbstractButton) { // val w = c.getTopLevelAncestor() // if (w is Window) { // w.setAlwaysOnTop(c.isSelected()) // } // } } } return JPanel(BorderLayout()).apply { add(cb, BorderLayout.NORTH) } } fun main(args: Array<String>) { EventQueue.invokeLater { JFrame("kotlin swing").apply { defaultCloseOperation = JFrame.EXIT_ON_CLOSE add(makeUI()) size = Dimension(320, 240) setLocationRelativeTo(null) setVisible(true) } } } }} #twocolumn ** インターフェイス、匿名内部クラス、throws [#tb58a862] - `addTreeWillExpandListener(object: TreeWillExpandListener() { ...`と記述すると`error: this class does not have a constructor`とエラーになる - インターフェイスから匿名内部クラスのインスタンスを生成する場合は`()`は不要で、`addTreeWillExpandListener(object: TreeWillExpandListener { ...`と記述する -- [https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions SAM Conversions - Calling Java from Kotlin - Kotlin Programming Language] #twocolumn `Java` #code{{ import java.awt.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.plaf.IconUIResource; import javax.swing.tree.*; public class ThrowsExample { public JComponent makeUI() { JPanel p = new JPanel(new GridLayout(1, 0, 5, 5)); p.add(new JScrollPane(new JTree())); p.add(new JScrollPane(makeTree())); p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); return p; } private static JTree makeTree() { Icon icon = new EmptyIcon(); UIManager.put("Tree.expandedIcon", new IconUIResource(icon)); UIManager.put("Tree.collapsedIcon", new IconUIResource(icon)); JTree tree = new JTree(); tree.setEditable(true); tree.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); int row = 0; while (row < tree.getRowCount()) { tree.expandRow(row++); } tree.addTreeWillExpandListener(new TreeWillExpandListener() { @Override public void treeWillExpand(TreeExpansionEvent e) throws ExpandVetoException { //throw new ExpandVetoException(e, "Tree expansion cancelled"); } @Override public void treeWillCollapse(TreeExpansionEvent e) throws ExpandVetoException { throw new ExpandVetoException(e, "Tree collapse cancelled"); } }); return tree; } public static void main(String[] args) { EventQueue.invokeLater(() -> { JFrame f = new JFrame(); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.getContentPane().add(new ThrowsExample().makeUI()); f.setSize(320, 240); f.setLocationRelativeTo(null); f.setVisible(true); }); } } class EmptyIcon implements Icon { @Override public void paintIcon(Component c, Graphics g, int x, int y) { /* Empty icon */ } @Override public int getIconWidth() { return 0; } @Override public int getIconHeight() { return 0; } } }} #twocolumn `Kotlin` #code{{ import java.awt.* import javax.swing.* import javax.swing.event.* import javax.swing.plaf.IconUIResource import javax.swing.tree.* fun makeUI(): JComponent { val emptyIcon = EmptyIcon() UIManager.put("Tree.expandedIcon", IconUIResource(emptyIcon)) UIManager.put("Tree.collapsedIcon", IconUIResource(emptyIcon)) val tree = JTree().apply { setEditable(true) border = BorderFactory.createEmptyBorder(4, 4, 4, 4) addTreeWillExpandListener(object: TreeWillExpandListener { //@Throws(ExpandVetoException::class) override fun treeWillExpand(e: TreeExpansionEvent) { //throw ExpandVetoException(e, "Tree expansion cancelled") } //@Throws(ExpandVetoException::class) override fun treeWillCollapse(e: TreeExpansionEvent) { throw ExpandVetoException(e, "Tree collapse cancelled") } }) } var row = 0; while (row < tree.getRowCount()) { tree.expandRow(row++); } return JPanel(GridLayout(1, 0)).apply { setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)) add(JScrollPane(JTree())) add(JScrollPane(tree)) } } class EmptyIcon: Icon { override fun paintIcon(c: Component, g: Graphics , x: Int, y: Int) { /* Empty icon */ } override fun getIconWidth(): Int = 0 override fun getIconHeight(): Int = 0 } fun main(args: Array<String>) { EventQueue.invokeLater { JFrame("kotlin swing").apply { defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE add(makeUI()) size = Dimension(320, 240) setLocationRelativeTo(null) setVisible(true) } } } }} #twocolumn ** Optional [#c0e18689] - `Optional#orElse(...)`は、`let {...} ?: ...`に変換 -- `Integer stepSize = Optional.ofNullable(stepSizeMap.get(calendarField)).orElse(1);` -- `val stepSize = stepSizeMap.get(calendarField).let { it } ?: 1` - 例えば`SpinnerDateModel#getNextValue(...)`メソッドを`override fun getNextValue(): Object = Calendar.getInstance().apply { ...`のように変換すると、`error: type mismatch: inferred type is Date! but Object was expected`とエラーになる - `override fun getNextValue(): Any = Calendar.getInstance().apply { ...`と`Any`を使用するようオーバーライドする必要がある - `Date!`は、`Date`もしくは`Date?`の意味 -- [http://kotlinlang.org/docs/reference/java-interop.html#null-safety-and-platform-types Calling Java from Kotlin - Kotlin Programming Language] -- `T! means "T or T?"` #twocolumn `Java` #code{{ import java.awt.*; import java.text.*; import java.util.*; import javax.swing.*; import javax.swing.text.*; public class OptionalExample { private JComponent makeUI() { SimpleDateFormat format = new SimpleDateFormat( "mm:ss, SSS", Locale.getDefault()); DefaultFormatterFactory factory = new DefaultFormatterFactory( new DateFormatter(format)); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.clear(Calendar.MINUTE); calendar.clear(Calendar.SECOND); calendar.clear(Calendar.MILLISECOND); Date d = calendar.getTime(); JSpinner sp1 = new JSpinner(new SpinnerDateModel( d, null, null, Calendar.SECOND)); JSpinner.DefaultEditor ed1 = (JSpinner.DefaultEditor) sp1.getEditor(); ed1.getTextField().setFormatterFactory(factory); HashMap<Integer, Integer> stepSizeMap = new HashMap<>(); stepSizeMap.put(Calendar.HOUR_OF_DAY, 1); stepSizeMap.put(Calendar.MINUTE, 1); stepSizeMap.put(Calendar.SECOND, 30); stepSizeMap.put(Calendar.MILLISECOND, 500); JSpinner sp2 = new JSpinner(new SpinnerDateModel( d, null, null, Calendar.SECOND) { @Override public Object getPreviousValue() { Calendar cal = Calendar.getInstance(); cal.setTime(getDate()); Integer calendarField = getCalendarField(); Integer stepSize = Optional.ofNullable( stepSizeMap.get(calendarField)).orElse(1); cal.add(calendarField, -stepSize); return cal.getTime(); } @Override public Object getNextValue() { Calendar cal = Calendar.getInstance(); cal.setTime(getDate()); Integer calendarField = getCalendarField(); Integer stepSize = Optional.ofNullable( stepSizeMap.get(calendarField)).orElse(1); cal.add(calendarField, stepSize); return cal.getTime(); } }); JSpinner.DefaultEditor ed2 = (JSpinner.DefaultEditor) sp2.getEditor(); ed2.getTextField().setFormatterFactory(factory); JPanel p = new JPanel(); p.add(sp1); p.add(sp2); return p; } public static void main(String... args) { EventQueue.invokeLater(() -> { JFrame f = new JFrame(); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); f.getContentPane().add(new OptionalExample().makeUI()); f.setSize(320, 240); f.setLocationRelativeTo(null); f.setVisible(true); }); } } }} #twocolumn `Kotlin` #code{{ import java.awt.* import java.text.* import java.util.* import javax.swing.* import javax.swing.text.* fun makeUI(): JComponent { val format = SimpleDateFormat("mm:ss, SSS", Locale.getDefault()) val factory = DefaultFormatterFactory(DateFormatter(format)) val calendar = Calendar.getInstance().apply { set(Calendar.HOUR_OF_DAY, 0) clear(Calendar.MINUTE) clear(Calendar.SECOND) clear(Calendar.MILLISECOND) } val d = calendar.getTime() val sp1 = JSpinner(SpinnerDateModel(d, null, null, Calendar.SECOND)) val ed1 = sp1.getEditor() if (ed1 is JSpinner.DefaultEditor) { ed1.getTextField().setFormatterFactory(factory) } val stepSizeMap: HashMap<Int, Int> = hashMapOf( Calendar.HOUR_OF_DAY to 1, Calendar.MINUTE to 1, Calendar.SECOND to 30, Calendar.MILLISECOND to 500) val sp2 = JSpinner(object: SpinnerDateModel(d, null, null, Calendar.SECOND) { override fun getPreviousValue(): Any = Calendar.getInstance().apply { time = getDate() val stepSize = stepSizeMap.get(calendarField).let { it } ?: 1 add(calendarField, -stepSize) }.getTime() override fun getNextValue(): Any = Calendar.getInstance().apply { setTime(getDate()) val stepSize = stepSizeMap.get(calendarField).let { it } ?: 1 add(calendarField, stepSize) }.getTime() }) val ed2 = sp2.getEditor() if (ed2 is JSpinner.DefaultEditor) { ed2.getTextField().setFormatterFactory(factory) } return JPanel().apply { add(sp1) add(sp2) } } fun main(args: Array<String>) { EventQueue.invokeLater { JFrame("kotlin swing").apply { defaultCloseOperation = WindowConstants.EXIT_ON_CLOSE add(makeUI()) size = Dimension(320, 240) setLocationRelativeTo(null) setVisible(true) } } } }} #twocolumn * コメント [#comment] #comment #comment