Панель компонентов движется после сворачивания рамы - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть такой код, где мне нужно создать несколько кнопок для настройки квадрата.Это работает, но после сворачивания фрейма текстовое поле перемещается по всему фрейму, и я не знаю почему.Я имею в виду, что когда я выполняю программу сначала, она находится в правильном положении, о котором я упоминал, используя метод setBounds (), но затем она располагается над квадратом.Так как я могу это исправить?

    import java.awt.*;
    import java.awt.event.*;
    import java.text.AttributedString;
    import javax.swing.*;
    import java.awt.font.TextAttribute;

     public class Square extends JFrame implements ActionListener {

      Button butt1 = new Button("Fill with yellow");
      Button butt2 = new Button("Fill with red");
      Button butt3 = new Button("Add label");
      Button butt4 = new Button("");

      Pan contentPane = new Pan();


      public Square() {
        super("Square");
        this.setBounds(200, 100, 670, 400);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.getContentPane().add(contentPane);
        contentPane.setBounds(0, 0, 670, 275);
        contentPane.setBackground(Color.BLACK);

        add(butt1);
        butt1.setBounds(25, 300, 190, 25);
        butt1.addActionListener(this);
        add(butt2);
        butt2.setBounds(235, 300, 190, 25);
        butt2.addActionListener(this);
        butt3.setBounds(440, 300, 190, 25);
        butt3.addActionListener(this);
        add(butt3);
        add(butt4);

      }

      @Override
      public void actionPerformed(ActionEvent e) {
        Object o = e.getSource();
        if (o == butt1) {
            contentPane.draw(1);
        }
        else if (o == butt2) {
            contentPane.draw(2);
        }
        else if (o == butt3) {
            contentPane.draw(3);
        }
      }

      public static void main(String[] args) {
          Square w = new Square();
        w.setVisible(true);
      }
    }

    class Pan extends JPanel {
      Graphics g;
      Graphics2D g2;
      protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.GRAY);
            g.drawRect(240, 70, 150, 150);  
        }

      public void draw(int i) {

          g = getGraphics();
          super.paintComponent(g);
          g2 = (Graphics2D) g.create();
         switch(i) {
        case 1: g2.setColor(Color.yellow);
            g2.fillRect(240, 70, 150, 150); 
            break;
        case 2: g2.setColor(Color.red);
            g2.fillRect(240, 70, 150, 150); 
            break;
        case 3:
            g.setColor(Color.GRAY);
            g.drawRect(240, 70, 150, 150);   
            JTextField text = new JTextField(25);
            this.add(text);
            Button add = new Button("Add");
            add.setBounds(400, 230, 120, 25);
            this.add(add);
            text.setBounds(240, 230, 150, 25);

            Font font = new Font("Veranda", Font.BOLD|Font.ITALIC, 24);
                class AddButton extends JPanel implements ActionListener {
                    @Override
                    public void actionPerformed(ActionEvent ev) {
                        AttributedString label = new AttributedString(text.getText());  
                        label.addAttribute(TextAttribute.FONT, font);
                        label.addAttribute(TextAttribute.FOREGROUND, Color.PINK);
                        g2.drawString(label.getIterator(), 240, 50);    
                    }
                }   
            AddButton listener = new AddButton();
            add.addActionListener(listener);
            break;
         }

         }
    }

1 Ответ

0 голосов
/ 26 февраля 2019

Хорошо, много основных проблем и недоразумений.

Swing использует менеджеры по расположению.Это, наверное, одна из первых вещей, которые вы снова теряете голову.Менеджеры макетов принимают решения о том, как лучше позиционировать компоненты, основываясь на их отдельных алгоритмах.

Начните с изучения Компоновка компонентов в контейнере для получения более подробной информации и их эффективного использования.Интерфейсы GUI - это сложные и динамичные вещи, и многие факторы влияют на определение размера и расположения компонентов.

Рисование.Другая проблема, с которой сталкиваются новые разработчики, это понимание того, что они не контролируют систему окраски.Swing использует пассивную систему рендеринга, что означает, что он будет рисовать, когда сочтет это необходимым.

Вы можете дать подсказки, когда новый проход рисования должен быть выполнен, вызвав repaint, но система должна решитьчто и когда что-то должно быть нарисовано.

g = getGraphics(); - плохая идея на многих уровнях.Помимо возможности вернуть null, это не что иное, как снимок последнего прохода краски, и будет отброшено, когда произойдет новый проход краски.

Вызов super.paintComponent(g); за пределами прохода краски такжеплохая идея.На самом деле, редко когда-либо возникает необходимость вызывать какой-либо из методов рисования напрямую.

Это НЕ то, как следует выполнять нестандартное рисование.Начните с того, что Выполнение пользовательской живописи и Рисование в AWT и Swing , чтобы узнать, как работает живопись и как с ней работать

Кроме того, смешивая тяжелый вес (AWT) и легкие (Swing) компоненты, как правило, плохая идея, следует избегать как можно больше.

Пример ...

Итак, я "взломал" ваш пример во что-то"немного" более разумно

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class Square extends JFrame implements ActionListener {

    JButton butt1 = new JButton("Fill with yellow");
    JButton butt2 = new JButton("Fill with red");
    JButton butt3 = new JButton("Add label");
    JButton butt4 = new JButton("");

    Pan contentPane = new Pan();

    public Square() {
        super("Square");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.getContentPane().add(contentPane);
        contentPane.setBackground(Color.BLACK);

        JPanel actions = new JPanel();
        actions.setBorder(new EmptyBorder(10, 10, 10, 10));

        actions.add(butt1);
        butt1.addActionListener(this);
        actions.add(butt2);
        butt2.addActionListener(this);
        butt3.addActionListener(this);
        actions.add(butt3);
//      actions.add(butt4);

        add(actions, BorderLayout.SOUTH);

        pack();
        setLocationRelativeTo(null);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object o = e.getSource();
        if (o == butt1) {
            contentPane.draw(1);
        } else if (o == butt2) {
            contentPane.draw(2);
        } else if (o == butt3) {
            contentPane.draw(3);
        }
    }

    public static void main(String[] args) {
        Square w = new Square();
        w.setVisible(true);
    }
}

class Pan extends JPanel {

    private int state = -1;
    private String text = null;

    public Pan() {
        Font font = new Font("Veranda", Font.BOLD | Font.ITALIC, 24);
        setFont(font);
        setLayout(new GridBagLayout());
        setBorder(new EmptyBorder(10, 10, 10, 10));
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(670, 275);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setColor(Color.GRAY);
        g2.drawRect(240, 70, 150, 150);
        switch (state) {
            case 1:
                g2.setColor(Color.yellow);
                g2.fillRect(240, 70, 150, 150);
                break;
            case 2:
                g2.setColor(Color.red);
                g2.fillRect(240, 70, 150, 150);
                break;
            case 3:
                g.setColor(Color.GRAY);
                g.drawRect(240, 70, 150, 150);
                break;
        }

        if (text != null) {
            AttributedString label = new AttributedString(text);
            label.addAttribute(TextAttribute.FONT, getFont());
            label.addAttribute(TextAttribute.FOREGROUND, Color.PINK);
            g2.drawString(label.getIterator(), 240, 50);
        }
    }

    public void draw(int i) {
        switch (i) {
            case 3:
                JTextField textField = new JTextField(25);
                JButton add = new JButton("Add");

                GridBagConstraints gbc = new GridBagConstraints();

                gbc.gridx = 0;
                gbc.gridy = 0;
                gbc.weighty = 1;
                gbc.anchor = GridBagConstraints.SOUTH;

                this.add(textField, gbc);
                gbc.gridx++;
                this.add(add, gbc);

                add.addActionListener(new ActionListener() {

                    @Override
                    public void actionPerformed(ActionEvent ev) {
                        text = textField.getText();
                        remove(textField);
                        remove(add);

                        revalidate();
                        repaint();
                    }
                });

                revalidate();
                repaint();

                break;
        }
        state = i;
        repaint();

    }
}

Magic numbers

В вашем коде полно так называемых "магических чисел".Это значения, значение которых неизвестно.

Запустите код и попробуйте изменить размер окна, и вы поймете, что я имею в виду.Вместо этого вы должны полагаться на «известные» значения, такие как getWidth и getHeight, чтобы лучше определить, как вы должны выводить вывод

...