我希望有人能帮助我。我无法找到描述这个问题的人。在扩展Window
的主类(JFrame
)中,我添加了一个扩展Panel
的类(JPanel
)的对象并将其添加到我的框架中。
到目前为止一切顺利,JPanel
类中的所有内容都显示出来,但是当我在我的主类中创建ShapeDef
对象(用于定义和绘制数字)时,然后尝试将其添加到Panel
,数字不会显示出来。为什么?我尝试使用revalidate()
和repaint
,但它似乎无法运作。
这里有一些代码:
主级:
public class Window extends JFrame implements ActionListener{
private JPanel myPanel;
private ShapeDef rect1, rect2;
public Window(){
super("Test Window");
setLayout(new BorderLayout());
myPanel = new Panel(new BorderLayout());
myPanel.setBackground(Color.BLACK);
rect1 = new ShapeDef("Rectangle", Color.green, 200, 300, 20, 80);
rect2 = new ShapeDef("Rectangle", Color.BLUE, 300, 700, 50, 40);
myPanel.add(rect1);
myPanel.add(rect2);
add(myPanel, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame myFrame = new PongInvaders();
myFrame.setSize(1280, 720);
myFrame.setBackground(Color.BLACK);
myFrame.pack();
myFrame.setVisible(true);
}
});
}
ShapeDef类:
public class ShapeDef extends JComponent{
private final Color color;
private final int x, y, width, height;
private final String type;
public ShapeDef(String type, Color color, int x, int y, int width, int height){
this.type = type;
this.color = color;
setBounds(x, y, width, height);
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
if(type.equalsIgnoreCase("Rectangle")){
g.setColor(color);
g.fillRect(0, 0, width, height);
}
else if(type.equalsIgnoreCase("Oval")){
g.setColor(color);
g.fillOval(x, y, width, height);
}
}
}
由李克强建议的当前版本的代码绘制了两个矩形,但是rect2在(0,0)处产生,而rect1在正确的坐标处产生。基本上这个问题已经回答了,所以谢谢大家的帮助。然而,为什么只有一个矩形在(0,0)产生,而另一个产生于设定坐标,当它们都被添加到同一个JPanel?
@MadProgrammer虽然你的答案不是我所期待的,但我认为这是我需要的答案。你绝对不辜负你的用户名。非常感谢您花时间教我更多关于创建更好的代码结构的知识。
我还想指出,其他答案非常有帮助和启发,他们也教我很多。
答案 0 :(得分:1)
你最大的问题是你要覆盖ShapeDef中的所有维度(x,y,width,height),而不是使用JCompoment方法(setSize,setPreferredSize(),setLocation)来设置它们。因此,您的ShapeDef没有大小,并且您在其中执行的任何绘制都将被图形剪辑阻止。
您还应该将 if (cb.GetChecked())
grid.Refresh();
的布局管理器显式设置为null
答案 1 :(得分:1)
向JPanel添加项目不要'出现
如果您延伸到JComponent
,则JComponent
本身已具有管理其维度和位置的属性,例如x
,y
,width
,{{1 }}
但是,您不是使用继承的属性,而是创建另一组具有相同名称的属性,这些属性可能会遮蔽继承的属性。
我发现您正在创建自己的height
,x
,y
,width
,这是不必要的。如果这些是为其他目的而创建的,您可能希望将它们重命名为其他目的。
除此之外,如果您只想要一些自定义绘图,则不必总是将height
课程扩展为ShapeDef
。你可以这样做:
JComponent
让你的JPanel持有ShapeDef的一个实例,并在JPanel中绘制它,只需这样做:
class ShapeDef
{
//other constructors and attributes not shown
public void draw(Graphics g){
//draw your drawings here..
}
}
答案 2 :(得分:1)
除了ControlAltDel在his Answer中所说的内容(将LayoutManager设置为null),您还必须为fillRect和fillOval设置x和y坐标为零。如果不这样做,由于剪裁,矩形将不可见。
public class ShapeDef extends JComponent {
private final Color color;
private int width, height;
private final String type;
public ShapeDef(String type, Color color, int x, int y, int width, int height){
this.type = type;
this.color = color;
this.width = width;
this.height = height;
this.setBounds(x, y, width, height); // creates a bounding box for your drawing
}
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
if(type.equalsIgnoreCase("Rectangle")){
g.setColor(color);
g.fillRect(0, 0, width, height); // draws inside of your bounding box
System.out.println("Rect");
}
else if(type.equalsIgnoreCase("Oval")){
g.setColor(color);
g.fillOval(0, 0, width, height); // draws inside of your bounding box
}
}
}
另外请考虑使用枚举而不是字符串作为类型参数。
答案 3 :(得分:1)
就个人而言,我认为你从错误的角度来看待解决方案。组件并没有真正设计用于实现这一目标,确保你可以让它们做到这一点,但它会导致一些有趣的路径,如果你不小心的话可能会让你在排水沟里流血。
相反,我定义了一个"基本"形状可以"画"从中,定义所有其他形状。
public interface Drawable {
public Color getStrokeColor();
public Color getFillColor();
public Rectangle getBounds();
public void paint(Graphics2D g2d);
}
public abstract class AbstractDrawable implements Drawable {
private Color strokeColor;
private Color fillColor;
public AbstractDrawable(Color strokeColor, Color fillColor) {
this.strokeColor = strokeColor;
this.fillColor = fillColor;
}
@Override
public Color getStrokeColor() {
return strokeColor;
}
@Override
public Color getFillColor() {
return fillColor;
}
}
public class RectangleDrawable extends AbstractDrawable {
private Rectangle bounds;
public RectangleDrawable(int x, int y, int width, int height, Color strokeColor, Color fillColor) {
super(strokeColor, fillColor);
bounds = new Rectangle(x, y, width, height);
}
@Override
public Rectangle getBounds() {
return bounds;
}
@Override
public void paint(Graphics2D g2d) {
g2d.setColor(getFillColor());
g2d.fill(getBounds());
g2d.setColor(getStrokeColor());
g2d.draw(getBounds());
}
}
public class OvalDrawable extends AbstractDrawable {
private Ellipse2D bounds;
public OvalDrawable(int x, int y, int width, int height, Color strokeColor, Color fillColor) {
super(strokeColor, fillColor);
bounds = new Ellipse2D.Double(x, y, width, height);
}
@Override
public Rectangle getBounds() {
return bounds.getBounds();
}
@Override
public void paint(Graphics2D g2d) {
g2d.setColor(getFillColor());
g2d.fill(bounds);
g2d.setColor(getStrokeColor());
g2d.draw(bounds);
}
}
然后我有一个能够管理和绘画的专用组件
public class DrawablePane extends JPanel {
private List<Drawable> drawables;
public DrawablePane() {
drawables = new ArrayList<>(25);
}
public void add(Drawable drawable) {
drawables.add(drawable);
repaint();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
for (Drawable drawable : drawables) {
drawable.paint(g2d);
}
g2d.dispose();
}
}
可能会使用类似......
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DrawablePane pane = new DrawablePane();
pane.add(new RectangleDrawable(10, 10, 100, 150, Color.YELLOW, Color.GREEN));
pane.add(new OvalDrawable(100, 20, 50, 50, Color.MAGENTA, Color.BLUE));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
答案 4 :(得分:0)
您的ShapeDef
课程应确定其大小和位置。您可以将其定义如下:
public class ShapeDef extends JComponent {
private final Color color;
private final String type;
public ShapeDef(String type, Color color, int x, int y, int width, int height) {
this.type = type;
this.color = color;
setPreferredSize(new Dimension(width, height));
setLocation(new Point(x, y));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (type.equalsIgnoreCase("Rectangle")) {
g.setColor(color);
g.fillRect(getX(), getY(), getSize().width, getSize().height);
System.out.println("Rect");
} else if (type.equalsIgnoreCase("Oval")) {
g.setColor(color);
g.fillOval(getX(), getY(), getSize().width, getSize().height);
}
}
}
然后你可以在你的窗口类中使用它:
public class MyWindow extends JFrame {
private JPanel myPanel;
private ShapeDef shape;
public MyWindow() {
super("Test Window");
setLayout(new BorderLayout());
myPanel = new JPanel(new BorderLayout());
myPanel.setBackground(Color.BLACK);
shape = new ShapeDef("Rectangle", Color.green, 200, 300, 20, 80);
myPanel.add(shape, BorderLayout.CENTER);
add(myPanel, BorderLayout.CENTER);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame myFrame = new MyWindow();
myFrame.pack();
myFrame.setVisible(true);
}
});
}
}
你真的不需要那个定制的Panel
课,关于你在做什么。