3 Stimmen

Die Größenänderung von hinzugefügten bemalten Komponenten und das seltsame Swing-Verhalten

Ich habe seit Tagen dieses Problem, das mich stört. Ich arbeite an einem speziellen Malprogramm. Ich habe ein JPanel erstellt und benutzerdefinierte jComponents hinzugefügt, die mit der paint(..) Methode gemalt werden. Das Problem ist, dass immer wenn ich das Fenster neu dimensioniere, alle hinzugefügten Komponenten "verschwinden" (oder einfach nicht gemalt werden), sodass ich letztendlich einen leeren Rahmen habe.

Außerdem habe ich einige seltsame Verhaltensweisen von Swing bei Verwendung dieser Methode bemerkt. Ich habe Kommentare zum Code hinzugefügt, die dieses Problem beschreiben.

package simple;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

import javax.swing.*;

public class SimpleFrame extends JFrame {
    JPanel paintArea;
    SimpleCanvas c1;
    SimpleCanvas c2;
    ArrayList list;

    public static void main(String[] args) {
        SimpleFrame frame = new SimpleFrame();

    }

    public SimpleFrame() {
        super("Test");
        setSize(600,500);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        //Das Panel, zu dem meine SimpleCanvas-Objekte hinzugefügt werden
        paintArea = new JPanel();
        paintArea.setPreferredSize(new Dimension(600, 500)); 
        paintArea.addMouseListener(new paintAreaMouseEvents());
        getContentPane().add(paintArea, BorderLayout.CENTER);

        setVisible(true);
        paintArea.setVisible(true);

        //Eine Liste, um alle Objekte zusammenzuhalten
        list = new ArrayList(10);

        //Das Gleiche wie in der Klasse paintAreaMouseEvent, funktioniert aber nicht
        SimpleCanvas c = new SimpleCanvas();
        c.setBounds(60, 100, 100, 50);
        list.add(c);
        paintArea.add(list.get(list.size() - 1));
        paintArea.repaint();
    }
    //Wenn Sie mit der Maus klicken, wird ein Oval erstellt
    class paintAreaMouseEvents extends MouseAdapter {
        @Override
        //Das funktioniert.
        public void mouseClicked (MouseEvent me) {
            SimpleCanvas c = new SimpleCanvas();
            c.setBounds(me.getX() - 50, me.getY() - 25, 100, 50);

            list.add(c);
            paintArea.add(list.get(list.size() - 1));
            paintArea.repaint();
        }
    }
}

Und hier ist die SimpleCanvas-Klasse

package simple;

import java.awt.*;

import javax.swing.JComponent;

public class SimpleCanvas extends JComponent {
    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(Color.BLUE);
        g.fillOval(0, 0, 100, 50);
    }
}

Danke :)

Übrigens: Ich wollte nur sagen, dass diese Seite erstaunlich ist. Ich war hier oft unterwegs, während ich Google benutzte, und jetzt habe ich mich endlich entschlossen, ein Konto zu erstellen.

6voto

Hovercraft Full Of Eels Punkte 280443

Ihr Problem ist ein Layout-Problem. Fügen Sie hinzu:

System.out.println(getSize());

Zum paint-Methode Ihres JComponent, um zu sehen, was passiert, wenn Sie das GUI neu dimensionieren.

Dies geschieht, weil das Ändern der Größe die Aktionen des Layout-Managers aufruft.

Um dies zu lösen, verwenden Sie nicht setBounds(...) zum Größenfestlegen von Komponenten, sondern die Layout-Manager. Überschreiben Sie auch die getPreferredSize-Methode Ihres JComponent, wenn Sie möchten, dass die Layout-Manager eine bestimmte Größe respektieren. Malen Sie schließlich nicht mit der paint-Methode, sondern mit der paintComponent-Methode. Die Tutorials werden erklären warum.

Außerdem, wenn Sie unbedingt etwas mit absoluter Positionierung positionieren müssen, dann muss der Container ein Null-Layout verwenden:

  // Das Panel, zu dem meine SimpleCanvas-Objekte hinzugefügt werden
  paintArea = new JPanel(null);

Bearbeiten
Wenn ich etwas ähnliches wie Ihr Programm oben machen würde, würde ich neue Komponenten nicht zu einem JPanel hinzufügen, sondern würde einfach eine Liste von Shapes im Zeichen-Panel halten und die Shapes in seiner paintComponent-Methode mit einer for-Schleife zeichnen. Zum Beispiel:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

public class SimpleFrame2 extends JPanel {
   private static final Color ELLIPSE_COLOR = Color.LIGHT_GRAY;
   private static final Color ELLIPSE_FILL_COLOR = Color.blue;
   private static final int PREF_W = 600;
   private static final int PREF_H = 500;
   public static final int ELLIPSE_WIDTH = 100;
   public static final int ELLIPSE_HEIGHT = 50;
   private static final Stroke ELLIPSE_STROKE = new BasicStroke(2f);
   private List shapes = new ArrayList();

   public SimpleFrame2() {
      addMouseListener(new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent mEvt) {
            double x = mEvt.getX() - ELLIPSE_WIDTH / 2;
            double y = mEvt.getY() - ELLIPSE_HEIGHT / 2;
            double w = ELLIPSE_WIDTH;
            double h = ELLIPSE_HEIGHT;
            shapes.add(new Ellipse2D.Double(x, y, w, h));
            repaint();
         }
      });
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      // zur Darstellung glatter Kanten
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setStroke(ELLIPSE_STROKE);
      for (Shape shape : shapes) {
         g2.setColor(ELLIPSE_FILL_COLOR);
         g2.fill(shape);
         g2.setColor(ELLIPSE_COLOR);
         g2.draw(shape);
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("SimpleFrame2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new SimpleFrame2());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Bearbeiten 2
mit Ziehen von Formen

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
public class SimpleFrame3 extends JPanel {
   private static final Color ELLIPSE_COLOR = Color.LIGHT_GRAY;
   private static final Color ELLIPSE_FILL_COLOR = Color.blue;
   private static final int PREF_W = 600;
   private static final int PREF_H = 500;
   public static final int ELLIPSE_WIDTH = 100;
   public static final int ELLIPSE_HEIGHT = 50;
   private static final Stroke ELLIPSE_STROKE = new BasicStroke(2f);
   private List rects = new ArrayList();

   public SimpleFrame3() {
      MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
      addMouseListener(myMouseAdapter);
      addMouseMotionListener(myMouseAdapter);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      // zur Darstellung glatter Kanten
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setStroke(ELLIPSE_STROKE);
      for (RectangularShape rect : rects) {
         g2.setColor(ELLIPSE_FILL_COLOR);
         g2.fill(rect);
         g2.setColor(ELLIPSE_COLOR);
         g2.draw(rect);
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   class MyMouseAdapter extends MouseAdapter {
      private RectangularShape selectedRect = null;
      private Point deltaPt = null;

      @Override
      public void mousePressed(MouseEvent mEvt) {
         if (mEvt.getButton() != MouseEvent.BUTTON1) {
            return;
         }

         if (rects.size() > 0) {
            for (int i = rects.size() - 1; i >= 0; i--) {
               if (rects.get(i).contains(mEvt.getPoint())) {
                  selectedRect = rects.get(i);
                  rects.remove(selectedRect);
                  rects.add(rects.size(), selectedRect);
                  deltaPt = new Point(mEvt.getX() - selectedRect.getBounds().x,
                        mEvt.getY() - selectedRect.getBounds().y);
                  repaint();
                  return;
               }
            }
         }
         double x = mEvt.getX() - ELLIPSE_WIDTH / 2;
         double y = mEvt.getY() - ELLIPSE_HEIGHT / 2;
         double w = ELLIPSE_WIDTH;
         double h = ELLIPSE_HEIGHT;
         Ellipse2D ellipse = new Ellipse2D.Double(x, y, w, h);
         rects.add(ellipse);
         selectedRect = ellipse;
         deltaPt = new Point((int)(mEvt.getX() - x), (int)(mEvt.getY() - y));
         repaint();
      }

      @Override
      public void mouseDragged(MouseEvent e) {
         if (selectedRect != null) {
            Rectangle bounds = selectedRect.getBounds();
            bounds.setLocation(e.getX() - deltaPt.x, e.getY() - deltaPt.y);
            selectedRect.setFrame(bounds.x, bounds.y, bounds.width, bounds.height);
            repaint();
         }
      }

      @Override
      public void mouseReleased(MouseEvent e) {
         if (selectedRect != null) {
            repaint();
            selectedRect = null;
         }
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("SimpleFrame3");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new SimpleFrame3());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X