java качается динамически, добавляя пользовательскую кнопку - PullRequest
0 голосов
/ 25 марта 2020

У меня проблема с динамическим добавлением компонентов в JPanel с абсолютной разметкой (фактически не с добавлением, а с сохранением ранее добавленных компонентов). Я могу вставить одну пользовательскую кнопку круга в jpanel на фрейме, но у меня проблема с отображением объектов, которые я добавил ранее.

Почти 20 лет go Я написал приложение для проверки кратчайшего пути и аналогичных алгоритмов. Выглядело это так: я добавил помеченные узлы на панель, а затем соединил их, используя помеченную линию. Затем я рассчитал пути. Я не использовал Swing с нескольких лет. Теперь я хотел бы повторить ту же задачу в Swing. Конечно, у меня нет копии моего старого приложения. У меня проблема с самого начала: динамическое добавление пользовательских компонентов на панель. Панель имеет абсолютную компоновку. Пользователь должен выбрать опцию «Новый узел» из меню. Затем появляется диалоговое окно - приложение запрашивает имя нового узла. После ввода имени узел добавляется в место, когда щелкают мышью. Но у меня есть проблема, потому что я не могу отобразить кнопки, добавленные ранее - отображаются только новые. Я пытался сохранить старые кнопки вместе с их координатами в виде кортежа в списке - я сделал что-то не так.

Это казалось простым: подобное приложение показано в книге Core Java (MouseTest 10-я глава 1-я глава громкость), единственное отличие - автор dr aws один компонент, содержащий геометрические фигуры, созданные по щелчку мыши, но я хотел бы нарисовать свои пользовательские кнопки (точно два типа компонентов: пользовательские кнопки и компонент, представляющий линию с расстоянием) ярлык, соединяющий кнопки). Каждый объект должен быть отдельным компонентом. Пожалуйста, помогите мне решить мою проблему.

public class RoutingGame extends JFrame {
private Set<String> labelNames;
private JMenuBar menuBar;
private JMenu fileMenu;

public RoutingGame() {
    super();
    labelNames = new HashSet<>();
    setBounds(300, 200, 800, 600);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel npanel = new JPanel();
    getContentPane().add(npanel, BorderLayout.NORTH);
    npanel.setLayout(new FlowLayout(FlowLayout.LEADING));
    JPanel cpanel = new JPanel();
    getContentPane().add(cpanel, BorderLayout.CENTER);
    cpanel.setLayout(null);

    menuBar = new JMenuBar();
    fileMenu = new JMenu("File");
    JMenuItem nodeItem = new JMenuItem("New node");
    menuBar.add(fileMenu);
    fileMenu.add(nodeItem);
    setJMenuBar(menuBar);
    nodeItem.addActionListener(e -> {
        String s = "";
        while (s.isBlank()) {
            s = (String) JOptionPane.showInputDialog(
                    this,
                    "Choose a name for your new node:",
                    "Add node",
                    JOptionPane.PLAIN_MESSAGE,
                    null,
                    null,
                    "Node");
            }
        final String[] nodeName = {s};
        setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
        cpanel.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                RoundButton roundButton = new RoundButton(nodeName[0]);
                Insets insets = cpanel.getInsets();
                Dimension size = roundButton.getPreferredSize();

                roundButton.setBounds ( insets.left + e.getX()  - size.width / 2, insets.top + e.getY() - size.height / 2, size.width  , size.height );                    
                setCursor(Cursor.getDefaultCursor());
                cpanel.add( roundButton );
                cpanel.revalidate();
                cpanel.repaint();
                cpanel.removeMouseListener(this);
                }
            });
        });
    }
}
 public class RoundButton extends JButton {
    private static final int DEFAULT_WIDTH = 66;
    private static final int DEFAULT_HEIGHT = 66;
    private Shape shape;
    public RoundButton(String label) {
        super(label);
        setContentAreaFilled(false);
}
@Override
public Dimension getPreferredSize() {
    return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}

protected void paintComponent(Graphics g) {
    int diameter = Math.min(getWidth(), getHeight());
    int radius = diameter / 2;

    if (! getModel().isArmed()) {
        g.setColor(WHITE);
    } else {
        g.setColor( new Color(230, 230, 230) );
    }
    g.fillOval(getWidth() / 2 - radius, getHeight() / 2 - radius, diameter, diameter);
    g.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius, diameter, diameter);
    super.paintComponent(g);
}

protected void paintBorder(Graphics g) {
    int diameter = Math.min(getWidth(), getHeight());
    int radius = diameter / 2;
    g.setColor(getForeground() );
    g.drawOval(getWidth() / 2 - radius, getHeight() / 2 - radius, diameter - 1, diameter - 1);
    }
}


public class RoutingGameRunner {
    public static void main(String[] args) {
        EventQueue.invokeLater( () -> {
            try {
                RoutingGame window = new RoutingGame();
                window.setResizable(false);
                window.setVisible(true);
            } catch (Exception e) {
                 e.printStackTrace();
            }
        });
    }
}

1 Ответ

0 голосов
/ 25 марта 2020

Но у меня проблема, потому что я не могу отобразить кнопки, добавленные ранее

Почему вам нужно снова отображать кнопки? Если вы добавили их на панель, они не исчезнут, если у вас нет логина c для их удаления.

В любом случае, вы выполняли какую-либо отладку?

button.setBounds( xpos + mouseCoord[0]  - size.width / 2, ypos +  
    mouseCoord[1] - size.height / 2, size.width  , size.height );

Код, подобный приведенному выше, должен быть реструктурирован в нечто вроде:

int x = xpos + e.getX() - (size.width / 2);
int y = ypos + e.getY() - (size.height / 2);
button.setBounds(x, y, size.width, size.height);

Потому что теперь вы можете на самом деле добавьте некоторый код отладки, чтобы убедиться, что ваши расчеты верны:

System.out.println(x + " : " + y + " : " + size);

Код, подобный приведенному выше, будет проверять, что:

  1. вы фактически вызываете свой код зацикливания
  2. границы кнопки правильные

Я предполагаю, что расположение неправильное, а кнопки расположены друг над другом.

Я не понимаю эту логику c:

roundButton.setBounds ( insets.left + mouseCoord[0]  - size.width / 2, insets.top + mouseCoord[1] - size.height / 2, size.width  , size.height );
buttonTuples.add( new ButtonTuple(roundButton, mouseCoord[0], mouseCoord[1]));

Вы добавляете компонент сразу, а затем сохраняете другое местоположение в классе ButtonTuple.

Зачем вам даже нужны два последних параметра? Границы кнопки уже установлены.

Редактировать:

В дополнение ко всем вышеперечисленным предложениям, самая большая проблема заключается в том, что вам нужно создать новый экземпляр RoundButton:

roundButton = new RoundButton();
roundButton.setBounds(…);
...