添加到JComponent的JTextField,JSlider,JComboBox等不会显示在包含JComponent的JFrame中。似乎只有Graphics参数绘制允许绘画。包含的测试程序在我努力发现如何显示添加到JComponent的组件时,使用JPanel与JComponent进行比较。有没有办法让这些组件显示出来?
public class TestPaints {
public static void main(String[] args) {
new TestPaints();
}
JTextField _text1;
JLabel _label1 = new JLabel("Text1");
JTextField _text2;
JLabel _label2 = new JLabel("Text2");
TestPaints() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame("Paint a Widget");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(3, 2));
GridBagConstraints grid = new GridBagConstraints();
frame.add(new JLabel("TextField in JComponent "));
grid.gridx = 2;
frame.add(new JLabel("TextField in JPanel"), grid);
grid.gridy = 2;
grid.gridx = 1;
frame.add(new TestJComponent(), grid);
grid.gridx = 2;
frame.add(new TestJPanel(), grid);
grid.gridy = 3;
grid.gridx = 1;
/* tabbing between the two TextFields shows that keystrokes are seen */
frame.add(_label1, grid);
grid.gridx = 2;
frame.add(_label2, grid);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestJComponent extends JComponent {
public TestJComponent() {
setPreferredSize(new Dimension(100, 30));
_text1 = new JTextField(6);
_text1.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
_label1.setText(_text1.getText());
_label1.repaint();
}
});
_text1.setOpaque(true);
_text1.setVisible(true);
add(_text1);
/* This doesn't work
JPanel panel = new JPanel();
panel.add(_text1);
add(panel); */
setOpaque(true);
setVisible(true);
setBackground(Color.green);
}
public void paint(Graphics g) {
super.paint(g); // did not do background. Rectangle r = g.getClipBounds(); // needs this
g.setColor(getBackground());
g.fillRect(r.x, r.y, r.width, r.height);
/* Variations such as these don't work */
_text1.setOpaque(true);
_text1.setVisible(true);
_text1.paintComponents(g);
}
}
class TestJPanel extends JPanel {
TestJPanel() {
_text2 = new JTextField(6);
_text2.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
_label2.setText(_text2.getText());
_label2.repaint();
}
});
add(_text2);
setBackground(Color.blue);
}
}
}
答案 0 :(得分:3)
编辑:您需要为JComponent提供一个布局,例如FlowLayout,以便组件正确显示,因为它没有像JPanel那样的默认布局。因此,将setLayout(new FlowLayout())
添加到JComponent的构造函数
你有:
frame.setLayout(new GridLayout(3, 2));
然后尝试使用GridBagConstraints将组件添加到JFrame的contentPane,这没有意义。如果你想使用这些约束,那么容器需要使用GridBagLayout,而不是GridLayout。
这也是危险的代码:
public void paint(Graphics g) {
super.paint(g); // did not do background. Rectangle r = g.getClipBounds(); // needs this
g.setColor(getBackground());
g.fillRect(r.x, r.y, r.width, r.height);
/* Variations such as these don't work */
_text1.setOpaque(true);
_text1.setVisible(true);
_text1.paintComponents(g);
}
你应该重写JComponent的paintComponent方法,而不是它的paint方法(调用super.paintComponent),不应该在任何绘制方法中直接设置组件可见性或调用组件的paintComponents方法。
另一个问题:不要在Swing文本组件中使用KeyListeners,而是将DocumentListener添加到组件的Document中。否则,您可能会破坏文本组件的某些功能,并且您的侦听器也无法复制/粘贴,而DocumentListener将会这样做。
另一个问题,主要问题:您需要为JComponent提供布局。它不像JPanel那样默认为FlowLayout。这就是添加的组件未显示在其中的原因。
例如:
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
public class TestPaints2 {
private JTextField textField1 = new JTextField(8);
private JTextField textField2 = new JTextField(8);
private JLabel label1 = new JLabel("Text1");
private JLabel label2 = new JLabel("Text2");
public TestPaints2() {
textField1.getDocument().addDocumentListener(new MyDocListener(label1));
textField2.getDocument().addDocumentListener(new MyDocListener(label2));
TestJComponent2 jComponent = new TestJComponent2();
jComponent.add(textField1);
TestJPanel2 jPanel = new TestJPanel2();
jPanel.add(textField2);
JPanel mainPanel = new JPanel(new GridLayout(0, 2));
mainPanel.add(new JLabel("JComponent"));
mainPanel.add(new JLabel("JPanel"));
mainPanel.add(jComponent);
mainPanel.add(jPanel);
mainPanel.add(label1);
mainPanel.add(label2);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private class MyDocListener implements DocumentListener {
private JLabel label;
public MyDocListener(JLabel label) {
this.label = label;
}
@Override
public void changedUpdate(DocumentEvent e) {
updateLabel(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
updateLabel(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
updateLabel(e);
}
private void updateLabel(DocumentEvent e) {
Document doc = e.getDocument();
int offset = doc.getLength();
try {
String text = doc.getText(0, offset);
label.setText(text);
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new TestPaints2());
}
}
class TestJComponent2 extends JComponent {
private static final Color BG = Color.GREEN;
private static final int GAP = 5;
public TestJComponent2() {
setOpaque(true);
setBackground(BG);
setLayout(new FlowLayout());
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
}
}
class TestJPanel2 extends JPanel {
private static final Color BG = Color.BLUE;
private static final int GAP = 5;
public TestJPanel2() {
setBackground(BG);
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
}
}