Хорошо, много основных проблем и недоразумений.
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();
}
}
В вашем коде полно так называемых "магических чисел".Это значения, значение которых неизвестно.
Запустите код и попробуйте изменить размер окна, и вы поймете, что я имею в виду.Вместо этого вы должны полагаться на «известные» значения, такие как getWidth
и getHeight
, чтобы лучше определить, как вы должны выводить вывод