JavaのSwingにて、JPanelの内容を継承クラスに書きたいがぬるぽが発生してしまう

アコーディオンというと「開くのはひとつだけ」というイメージがあります(だから「風」なんでしょうが^^;
展開・折り畳みが個別にできるようなので、Expanderとかのほうがあっていそうに思います(以後Expanderと呼称します)

参考サイトの作りは(個人的には)あまりいい作りに思えません(サンプルを作りやすい構造にしたかった等の都合があったのかもしれません)

Expanderはヘッダーのテキストとなんらかのコンテンツを持ち、ヘッダーのクリックでコンテンツの展開・折り畳みをするコンポーネントですね?

Expanderはコンテンツがなんであるかには興味はなく、単に渡されたコンテンツをそのまま使うだけでいいはずです。
なのでabstractである必要はないですし、継承する必要もありません。

パターンごとにクラスを作りたければ、「コンテンツ」として好きに作ればいいでしょう^^

java

1import javax.swing.*;2import java.awt.*;3import java.awt.event.*;4import java.util.stream.Stream;5 6 7public class Main extends JFrame {8 public static void main(String[] args) {9 new Main().setVisible(true);10 }11 12 private final JLabel label = new JLabel(" ");13 14 public Main() {15 setDefaultCloseOperation(EXIT_ON_CLOSE);16 setSize(300, 200);17 setLocationRelativeTo(null);18 19 add(label, BorderLayout.NORTH);20 21 var box = Box.createVerticalBox();22 23 var cp = new CheckBoxPanel("111", "222");24 box.add(new Expander("CheckBox", cp));25 box.add(Box.createVerticalStrut(5));26 27 var rp = new RadioButtonPanel("aaa", "bbb", "ccc");28 box.add(new Expander("RadioButton", rp));29 box.add(Box.createVerticalStrut(5));30 31 box.add(Box.createVerticalGlue());32 add(new JScrollPane(box));33 }34 35 class CheckBoxPanel extends JPanel {36 CheckBoxPanel(String... texts) {37 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));38 Stream.of(texts).map(JCheckBox::new).forEach(b -> {39 add(b);40 b.addActionListener(e -> label.setText((b.isSelected() ? "selected " : "unselected ") + b.getText()));41 });42 }43 }44 45 class RadioButtonPanel extends JPanel {46 RadioButtonPanel(String... texts) {47 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));48 var bg = new ButtonGroup();49 Stream.of(texts).map(JRadioButton::new).forEach(b -> {50 b.setSelected(getComponentCount() == 0);51 add(b);52 bg.add(b);53 54 b.addItemListener(e -> {55 if (e.getStateChange() == ItemEvent.SELECTED) {56 label.setText("selected " + b.getText());57 }58 });59 });60 }61 }62}63 64class Expander extends JPanel {65 Expander(String header, JComponent content) {66 super(new BorderLayout());67 68 var label = new JLabel("▼ " + header);69 label.addMouseListener(new MouseAdapter() {70 @Override public void mousePressed(MouseEvent e) {71 content.setVisible(!content.isVisible());72 label.setText(String.format("%s %s", content.isVisible() ? "△" : "▼", header));73 revalidate();74 EventQueue.invokeLater(() -> scrollRectToVisible(content.getBounds()));75 }76 });77 add(label, BorderLayout.NORTH);78 79 content.setVisible(false);80 add(content, BorderLayout.CENTER);81 }82 83 @Override public Dimension getMaximumSize() {84 var d = getPreferredSize();85 d.width = Short.MAX_VALUE;86 return d;87 }88}

アプリ動画

コメントを投稿

0 コメント