2

各列と各行で、一度に 1 つのボタンしか選択できないように、JRadioButton-Matrix を設定しようとしています。次のコードがあります。

JRadioButton[][] button = new JRadioButton[names.length][names.length];
ButtonGroup[] r = new ButtonGroup[names.length];
ButtonGroup[] c = new ButtonGroup[names.length];
for (int i = 0; i < names.length; i++) {
    r[i] = new ButtonGroup();
    c[i] = new ButtonGroup();
}
for (int i = 0; i < names.length; i++) {
        for (int j = 0; j < names.length; j++) {
                    button[i][j] = new JRadioButton();
                    r[i].add(button[i][j]);
                    c[j].add(button[i][j]);
        }
}

しかし、私がそれを実行すると、列だけが正しく動作します (つまり、c のグループのボタン)。ただし、パーツを c でコメントすると、行は適切に動作します。

物事を少し片付けるには (peeskillet に感謝):

JRadioButton のこの 4 x 4 マトリックスがあるとします。

O   O   O   O

O   O   O   O

O   O   O   O

O   O   O   O

そして、次のような選択ができるようにしたいと考えています。

X   O   O   O       X   O   O   O      O   X   O   O

O   X   O   O       O   O   X   O      X   O   O   O

O   O   X   O       O   X   O   O      O   O   O   X

O   O   O   X       O   O   O   X      O   O   X   O

上記では、各列には 1 つのみがあり、各行には 1 つのみがあります。次の例は不可能です。

X   X   O   O       X   O   O   O

O   O   O   O       O   X   O   O

O   O   X   O       O   X   O   O

O   O   O   X       O   O   O   X

ただし、問題は、上記の左のマトリックスのように選択できますが、右のマトリックスは選択できません。次の部分にコメントすると:

ButtonGroup[] c = new ButtonGroup[names.length]; 
c[i] = new ButtonGroup();
c[j].add(button[i][j]);

その場合、右上の行列は可能ですが、左側はできません。

4

3 に答える 3

2

いいえ、AbstractButtonデフォルトButtonModel(当然のことながら という名前DefaultButtonModel) を使用するサブクラスは、単一の にのみ含めることができますButtonGroup

詳細については、ButtonGroup.add(...)およびButtonModel.setGroup(... ) を参照してください。

マトリックスの知識を持ち、複数の選択を可能にする特別なButtonGroupサブクラスを作成することは可能です (いくつかのハックがあると思います)。1 つのラジオボタン (相互に排他的) と複数のチェックボックス (複数選択可) のグループを作成したことがありますが、うまくいきました。:-) 今はコードにアクセスできませんが、興味があれば後でコードを更新するかもしれません。

于 2013-12-25T13:08:28.640 に答える
1

カスタム ButtonGroup (@Harald によって既に提案されているように) は間違いなく進むべき道です。

buttonModel とグループの責任が少し奇妙に混ざり合っているため、完全に自明ではありません。覚えておくべき基本的な調整は、グループが独自の選択状態を維持する必要があることです (モデルの選択された状態に依存するのとは対照的です)。

以下の POC 実装は、それをマトリックス (list-of-(lists-of-buttonModels)) に保持します。これには、null または選択されたと見なされるモデルが含まれます。内部更新は、各行と各列にnullでない要素が1つだけあるように、その行列を保持します(正式にテストする必要はありません:-)。確かに片付けの余裕はかなりあります...

/**
 * A buttonGroup that organizes selections in a matrix and guarantees 
 * to have at most one selection in each row and each column.
 */
public static class MatrixButtonGroup extends ButtonGroup {
    // matrix of the buttons
    private List<List<AbstractButton>> buttonMatrix;
    // sparse matrix of the selected models, contains nulls
    // everywhere except the unique selection for each row/column
    private List<List<ButtonModel>> selectionMatrix;

    public MatrixButtonGroup(List<AbstractButton> buttons, int columnCount) {
        if (buttons.size() % columnCount != 0) {
            throw new IllegalStateException("buttons count must be a multiple of columnCount");
        }
        int rowCount = buttons.size() / columnCount;
        buttonMatrix = new ArrayList<>();
        selectionMatrix = new ArrayList<>();
        int counter = 0;
        for (int row = 0; row < rowCount; row++) {
            List<AbstractButton> buttonsInRow = new ArrayList<>();
            List<ButtonModel> modelsInRow = new ArrayList<>();
            for (int column = 0; column < columnCount; column++) {
                modelsInRow.add(null);
                buttons.get(counter).getModel().setGroup(this);
                buttonsInRow.add(buttons.get(counter++));
            }
            selectionMatrix.add(modelsInRow);
            buttonMatrix.add(buttonsInRow);
        }
    }

    @Override
    public boolean isSelected(ButtonModel m) {
        for (int row = 0; row < selectionMatrix.size(); row++) {
            List<ButtonModel> modelsInRow = selectionMatrix.get(row);
            if (modelsInRow.contains(m)) return true;
        }
        return false;
    }

    /**
     * Implemented to select the model such that it is the
     * uniquely selected in the row/column of its button.
     */
    @Override
    public void setSelected(ButtonModel model, boolean selected) {
        if (model == null || !selected) return;
        if (isSelected(model)) return;
        int row = getRow(model);
        int column = getColumn(model);
        ButtonModel rowSelected = getSelectedForRow(row);
        ButtonModel columnSelected = getSelectedForColumn(column);
        // update internal selection state
        select(model, row, column);
        // unselect the old selection if necessary
        if (rowSelected != null) {
            rowSelected.setSelected(false);
        }
        if (columnSelected != null) {
            columnSelected.setSelected(false);
        }
        // select the new model
        model.setSelected(true);
    }


    /**
     * Update internal selection state to select the model such 
     * that there is exactly one model selected in the given 
     * row and column.
     */
    private void select(ButtonModel model, int row, int column) {
        // clear all in column
        for (int index = 0; index < selectionMatrix.size(); index++) {
            selectionMatrix.get(index).set(column, null);
        }
        List<ButtonModel> selectionRow = selectionMatrix.get(row);
        for (int index = 0; index < selectionRow.size(); index++) {
            selectionRow.set(index, null);
        }
        selectionRow.set(column, model);
    }

    /**
     * @return the column of the given model
     */
    private int getColumn(ButtonModel model) {
        for (int row = 0; row < buttonMatrix.size(); row++) {
            int column = getColumnInRow(buttonMatrix.get(row), model);
            if (column >= 0) return column;
        }
        throw new IllegalStateException("model not managed by this group");
    }

    /**
     * @return the row of the given model
     */
    private int getRow(ButtonModel model) {
        for (int row = 0; row < buttonMatrix.size(); row++) {
            if (getColumnInRow(buttonMatrix.get(row), model) >= 0) return row;
        }
        throw new IllegalStateException("model not managed by this group");
    }

    /**
     * @return the column of the model in the list
     */
    private int getColumnInRow(List<AbstractButton> list, ButtonModel model) {
        for (int column = 0; column < list.size(); column++) {
            if (list.get(column).getModel() ==  model) return column;
        }
        return -1;
    }


    /**
     * @return the selected buttonModel in the column or null if none
     * selected
     */
    private ButtonModel getSelectedForColumn(int column) {
        for (List<ButtonModel> selectionRow : selectionMatrix) {
            if (selectionRow.get(column) != null) return selectionRow.get(column);
        }
        return null;
   }

    /**
     * @return the selected buttonModel in the row or null if none
     * selected
     */
    private ButtonModel getSelectedForRow(int row) {
        List<ButtonModel> selectionRow = selectionMatrix.get(row);
        for (ButtonModel model : selectionRow) {
            if (model != null) return model;
        }
        return null;
    }


    /**
     * Implemented to return the first selected model, traversing
     * rows from first to last column.
     */
    @Override
    public ButtonModel getSelection() {
        for (List<ButtonModel> selectionRow : selectionMatrix) {
            for (ButtonModel model : selectionRow) {
                if (model != null) return model;
            }
        }
        return null;
    }

    @Override
    public int getButtonCount() {
        return buttonMatrix.size() * buttonMatrix.get(0).size();
    }

    // super overrides that still need to be done or are not supported 

    @Override
    public Enumeration<AbstractButton> getElements() {
        throw new UnsupportedOperationException("not yet implemented");
    }

    @Override
    public void clearSelection() {
        throw new UnsupportedOperationException("not yet implemented");
    }

    @Override
    public void add(AbstractButton b) {
       throw new UnsupportedOperationException("this button group is unmodifiable");
    }

    @Override
    public void remove(AbstractButton b) {
        throw new UnsupportedOperationException("this button group is unmodifiable");
    }
}

それは使用法です:

List<AbstractButton> buttons = new ArrayList<>();
for (int row = 0; row < 4; row++) {
    for (int column = 0; column < 4; column++) {
        buttons.add(new JRadioButton("row " + row + " col " + column));
    }
}
ButtonGroup p = new MatrixButtonGroup(buttons, 4);
JComponent content = new JPanel(new GridLayout(0, 4));
for (AbstractButton button : buttons) {
    content.add(button);
}
于 2013-12-25T18:55:17.650 に答える
1

あなたが探している機能は実行可能ですか?はい。以下は、私が意味するものの例です。私は多くの is ステートメントを使用しました。これを達成するための再帰的な方法があるかもしれませんが、それはさらに頭を悩ませます。例を見てみましょう。残念ながら、それは 9 つのボタンしか使用しませんでした。したがって、さらに使用したい場合は、さらに多くのコーディングが必要になります。基本的に私がしたことは、選択されているボタンごとに特定のボタンの選択を解除することだけでした。

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;

public class MultiButtonGroup extends JPanel implements ActionListener {

    JRadioButton rb1 = new JRadioButton("rb1");
    JRadioButton rb2 = new JRadioButton("rb2");
    JRadioButton rb3 = new JRadioButton("rb3");
    JRadioButton rb4 = new JRadioButton("rb4");
    JRadioButton rb5 = new JRadioButton("rb5");
    JRadioButton rb6 = new JRadioButton("rb6");
    JRadioButton rb7 = new JRadioButton("rb7");
    JRadioButton rb8 = new JRadioButton("rb8");
    JRadioButton rb9 = new JRadioButton("rb9");

    public MultiButtonGroup() {

        JRadioButton[][] buttons = {
            {rb1, rb2, rb3},
            {rb4, rb5, rb6},
            {rb7, rb8, rb9}
        };

        JPanel panel = new JPanel(new GridLayout(4, 4));
        for (JRadioButton[] rbs : buttons) {
            for (JRadioButton rbz : rbs) {
                rbz.addActionListener(new RadioListener());
                panel.add(rbz);
            }
        }

        JButton doSomething = new JButton("Do SOmething");
        setLayout(new BorderLayout());
        add(panel, BorderLayout.CENTER);
        add(doSomething, BorderLayout.SOUTH);

    }

    public void actionPerformed(ActionEvent e) {

    }

    private class RadioListener implements ActionListener {

        public void actionPerformed(ActionEvent e) {
            JRadioButton source = (JRadioButton) e.getSource();
            if (source == rb1) {
                if (rb1.isSelected()) {
                    rb2.setSelected(false);
                    rb3.setSelected(false);
                    rb4.setSelected(false);
                    rb7.setSelected(false);
                }
            } else if (source == rb2) {
                if (rb2.isSelected()) {
                    rb1.setSelected(false);
                    rb3.setSelected(false);
                    rb5.setSelected(false);
                    rb8.setSelected(false);
                }
            } else if (source == rb3) {
                if (rb3.isSelected()) {
                    rb2.setSelected(false);
                    rb1.setSelected(false);
                    rb6.setSelected(false);
                    rb9.setSelected(false);
                }
            } else if (source == rb4) {
                if (rb4.isSelected()) {
                    rb1.setSelected(false);
                    rb7.setSelected(false);
                    rb5.setSelected(false);
                    rb6.setSelected(false);
                }
            } else if (source == rb5) {
                if (rb5.isSelected()) {
                    rb4.setSelected(false);
                    rb6.setSelected(false);
                    rb2.setSelected(false);
                    rb8.setSelected(false);
                }
            } else if (source == rb6) {
                if (rb6.isSelected()) {
                    rb3.setSelected(false);
                    rb9.setSelected(false);
                    rb4.setSelected(false);
                    rb5.setSelected(false);
                }
            } else if (source == rb7) {
                if (rb7.isSelected()) {
                    rb1.setSelected(false);
                    rb4.setSelected(false);
                    rb8.setSelected(false);
                    rb9.setSelected(false);
                }
            } else if (source == rb8) {
                if (rb8.isSelected()) {
                    rb7.setSelected(false);
                    rb9.setSelected(false);
                    rb5.setSelected(false);
                    rb2.setSelected(false);
                }
            } else if (source == rb9) {
                if (rb9.isSelected()) {
                    rb6.setSelected(false);
                    rb3.setSelected(false);
                    rb8.setSelected(false);
                    rb7.setSelected(false);
                }
            }
        }
    }

    public static void createAndShowGui() {
        JFrame frame = new JFrame();
        frame.add(new MultiButtonGroup());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGui();
            }
        });
    }
}

ここに画像の説明を入力

于 2013-12-25T12:55:21.350 に答える