[英]JPanel doesn't display all custom made components
在JFrame中显示组件时遇到一个奇怪的问题。
我必须编写自己的GUI引擎(按钮,文本框等),而无需使用Swing。 仅允许使用JFrame / JPanel。
假设我要放置3个按钮。
我的按钮类:
public class Button extends JPanel implements MouseListener {
Rectangle r = new Rectangle();
String text;
int X,Y,W,H;
public Button(int x, int y, int w, int h, String t)
{
X=x;
Y=y;
W=w;
H=h;
this.setBackground(Color.CYAN);
addMouseListener(this);
r.setSize(w, h);
r.setLocation(x, y);
this.text = t;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.draw(r);
g2d.drawString(text, X+W/2, Y+H/2);
}
@Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
if((arg0.getButton()==1) && r.contains(arg0.getPoint()))
System.out.println(arg0.getPoint().toString());
}
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
在主类中,我创建一个JFrame和JPanel。 我将添加到JPanel 3按钮,最后将JPanel添加到JFrame,但是仅显示最后一个声明的按钮。
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame f = new JFrame("Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setBackground(Color.cyan);
JPanel j = new JPanel(new BorderLayout());
j.add(new Button(10,10,100,50,"text"));
j.add(new Button(10,100,100,50,"text2"));
j.add(new Button(300,10,100,50,"text3"));
f.add(j);
f.pack();
f.setSize(640, 400);;
f.setVisible(true);
}
我究竟做错了什么?
您的代码不遵守BorderLayout规则。 当使用容器将3个组件添加到BorderLayout而不指定BorderLayout位置时,它们都被添加到默认的BorderLayout.CENTER点,而最后添加的覆盖其他3个。在添加组件时,请考虑使用BorderLayout常数,或者使用其他布局管理器。 )。
话虽如此,我认为您最好完全改变路线。 而是考虑...
List<Button>
, paintComponent
方法中的列表,使单个JPanel绘制所有Button,并调用每个Button具有的draw(Graphics g)
方法 这将大大简化事情。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
public class FooGui extends JPanel {
private static final int PREF_W = 640;
private static final int PREF_H = 400;
private List<MyButton> btnList = new ArrayList<>();
public FooGui() {
addMouseListener(new MyMouse());
}
public void addButton(MyButton btn) {
btnList.add(btn);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (MyButton myButton : btnList) {
myButton.draw(g);
}
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
for (MyButton myButton : btnList) {
if (myButton.getRect().contains(e.getPoint())) {
System.out.println("Text: " + myButton.getText());
}
}
}
}
private static void createAndShowGui() {
FooGui fooGui = new FooGui();
fooGui.addButton(new MyButton(10,10,100,50,"text"));
fooGui.addButton(new MyButton(10,100,100,50,"text2"));
fooGui.addButton(new MyButton(300,10,100,50,"text3"));
JFrame frame = new JFrame("FooGui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(fooGui);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyButton {
private static final Color BK = Color.CYAN;
private static final Color TEXT_COLOR = Color.BLACK;
private int x;
private int y;
private int w;
private int h;
private String text;
private Rectangle rect;
public MyButton(int x, int y, int w, int h, String t) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.text = t;
rect = new Rectangle(x, y, w, h);
}
public void draw(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(BK);
g2.fill(rect);
g2.setColor(TEXT_COLOR);
FontMetrics metrics = g2.getFontMetrics();
Rectangle2D bounds = metrics.getStringBounds(text, g2);
int textX = (int) (x + (w - bounds.getWidth()) / 2);
int textY = (int) (y + (h + bounds.getHeight()) / 2);
g2.drawString(text, textX, textY);
}
public Rectangle getRect() {
return rect;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getW() {
return w;
}
public int getH() {
return h;
}
public String getText() {
return text;
}
}
此工作的目的是创建一个GUI,例如,当某些设备(例如旧手机)中没有实现的JButton,JLabel等时,可以使用该GUI。
好吧,这并不能真正回答我的问题。 您解决了自定义绘制按钮和标签的问题,但是GUI不仅具有绘画功能,还具有绘画功能。
我还问过您是否可以使用AWT的其他功能,例如MouseListeners,KeyListeners,Tab,布局管理器等。因为如果可以使用这些功能,那么就没有理由像气垫船那样完全重新发明轮子了。 。
如果您需要做的就是扩展JPanel并为按钮或标签做自定义绘制,那么代码的问题是您没有正确使用布局管理器。 那是框架的默认布局是BorderLayout,并且您不能将多个组件添加到BorderLayout的CENTER。
您发布的代码的第二个问题是您不会覆盖组件的getPreferredSize()
方法。 因此,大小将为0,并且布局管理器无法正确执行其工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.