# JPanel mit Graphics2D Objekten mit JScrollpane



## Markus_667 (20. Dez 2017)

Hallo Zusammen,

ich bin schon am verzweifeln und hoffe Ihr könnt mir helfen.
Habs auch schon an anderer Stelle Probiert aber eventuell ist das ja eher ein Problem für die Gaming Area.
Also ich zeichne ein JFrame dem übergebe ich ein JScrollPane und das JScrollpane bekommt ein JPanel übergeben.
Darin Zeichne ich mit der Maus Kreise und Vierecke (paintComponent mit g2d.draw(rect) usw.) die ich dann mit der Maus mit Linien vernetze und verschieben kann. Das klappt alles prima.
Nun möchte ich das Panel aber scrollbar machen, weil wenn ich die Vierecke (Recktangle2D) mit der Maus anfasse und aus dem JFrame Rand hinaus ziehen sind sie verschwunden und werden erst wieder dargestellt wenn ich das Fenster bis dahin aufziehe.

Die Scrollbalken sind da, aber ohne Funktion.
Wenn ich nun mit einer Schleife mehre JTextfield Objekte nacheinander zeichnen lasse (nur zum testen) bekommen die Scrollbalken auch eine Funktion.
Nur mit den Graphics Objekten will das nicht funktionieren.
Die unterschiedlichen Größenangaben waren auch nur zum testen so gewählt.

Im Prinzip versuche ich so etwas ähnliches wie der folgende Link darstellt zu programmieren.
http://www.pneditor.org/

Meine Zeichenarea schaut folgend aus.
(das ganze Programm ist zu groß um es komplett zu posten)
Was mache ich falsch ?

Vielen Dank schon mal...


```
public class ZeichenArea {
    public JScrollPane scrollPn;
    JFrame frame;
    GrafikObjekte grafikObj;
    Optionen optionenPanel;

    public ZeichenArea(Optionen optionenPanel) {
        grafikObj = new GrafikObjekte();
        grafikObj.setSize(1200,900);
        scrollPn = new JScrollPane(grafikObj,ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        AktionHandler aktion_handler = new AktionHandler(grafikObj, optionenPanel, scrollPn);
        grafikObj.addMouseListener(aktion_handler);
        grafikObj.addMouseMotionListener(aktion_handler);
           
        frame = new JFrame("Zeichenbrett");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(new Dimension(800,800));
        frame.setLocationRelativeTo(null);
    

        frame.addKeyListener(aktion_handler);
        //frame.add(scrollPn);
        frame.getContentPane().add(scrollPn,BorderLayout.CENTER);
        frame.setVisible(true);
    }

    public JFrame getFrame() {
        return frame;
    }

    public void setFrame(JFrame frame) {
        this.frame = frame;
    }
}
```


----------



## JuKu (20. Dez 2017)

Ich glaube das Problem ist, dass JScrollPane nicht weiß, wie groß das grafikObj ist.
Evtl. musst du irgendwo eine Größe festsetzen.


----------



## Markus_667 (21. Dez 2017)

Aber ich habe doch der ScrollPane das graphObj übergeben, sollte es dann nicht wissen wie groß es ist und wenn es sich ändert ?
Werde es auf jeden Fall morgen probieren... Danke


----------



## truesoul (21. Dez 2017)

Hallo.

Warum eröffnest du denn ein Thema, der das gleiche Problem wie in diesen Thread beschreibt?

Mal ein Beispiel:


```
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ScrollPane;
import java.awt.Toolkit;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ScrollPanelExample {

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

    ScrollPanelExample() {
        init();
    }

    void init() {
        JFrame frame = new JFrame();
        // Größe des Frames setzen
        frame.setPreferredSize(new Dimension(960, 960));

        MyPanel panel = new MyPanel();

        // ScrollPane braucht keine Größe
        ScrollPane scrollPane = new ScrollPane();
        // ScrollPane nimmt das Panel auf
        scrollPane.add(panel);

        frame.setContentPane(scrollPane);
        frame.pack();
        frame.setVisible(true);
    }

    class MyPanel extends JPanel {

        public MyPanel() {

            Toolkit tool = Toolkit.getDefaultToolkit();
            // Größe setzen anhand des Bildschirmauflösung
            setPreferredSize(tool.getScreenSize());
        }

        @Override
        protected void paintComponent(Graphics g) {
            g.drawRect(100, 150, 20, 20);
            g.drawRect(400, 350, 20, 20);
            g.drawRect(600, 600, 20, 20);
            g.drawRect(100, 600, 20, 20);
            g.drawRect(1200, 800, 20, 20);

        }
    }
}
```

Grüße


----------



## Markus_667 (21. Dez 2017)

Sorry für den doppelten Post  aber ich hab ziemlichen Zeitdruck und wollte damit nur einen größeren Personenkreis ansprechen.
Dein Beispiel hat zwar aktive Scrollbalken aber nicht aufgrund des Rechtecks welches du bei (1200, 800) platzierst.
Ich arbeite mit Laptop und Monitor, das Fenster nimmt die ScreenSize des Laptops beim öffnen.
Wenn ich es dann auf meinen Monitor ziehe, der deutlich größer ist, wird die ScreenSize nicht erneut ausgelesen.
Dadurch kann ich es an der unteren Ecke so weit ziehen bis die Scrollbalken verschwunden sind.
Platziere ich dann ein Objekt noch weiter "draußen" (also außerhalb der WQHD) ist das Panel auch nicht mehr Scrollbar. Füge ich aber wieder TextFelder hinzu, die über WQHD hinaus ragen, bleibt das Panel Scrollbar.
Das ScrollPanel orientiert sich daher leider nicht an den Rechtecken sondern nur an den anderen Objekten wie JTextfield.

Das ist aber glaube ich ein Ansatz den ich verwende wenn nichts mehr hilft.

Von daher vielen Dank dafür, es hat auch sehr geholfen das Ganze etwas näher zu verstehen.
Ich Teste mal noch die Antwort in dem zweiten Thread von thet1983 mit Hoffnung auf Erfolg


----------



## JuKu (22. Dez 2017)

Markus_667 hat gesagt.:


> Das ScrollPanel orientiert sich daher leider nicht an den Rechtecken sondern nur an den anderen Objekten wie JTextfield.



Richtig!
Was du in der paintComponent() Methode zeichnest, ist der JScrollPane völlig egal.
Es kommt auf die Größe der inneren Objekte drauf an. Und diese hast du bisher weder gesetzt noch überschrieben.


----------



## truesoul (22. Dez 2017)

Hi.

Also ein erweitertes Beispiel:


```
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.ScrollPane;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class ScrollPanelExample {

    private List<Shape> shapes = new ArrayList<>();
    private final int FRAME_WIDTH = 960;
    private final int FRAME_HEIGHT = 960;

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

    ScrollPanelExample() {
        createShapes();
        init();
    }

    void createShapes() {
        for (int i = 0; i < 10; i++) {
            shapes.add(getRectangle(new Random().nextInt(3840) + 1, new Random().nextInt(2160) + 1));
        }
    }

    void init() {
        JFrame frame = new JFrame();
        // Größe des Frames setzen
        frame.setPreferredSize(new Dimension(FRAME_WIDTH, FRAME_HEIGHT));

        MyPanel panel = new MyPanel();

        // ScrollPane braucht keine Größe
        ScrollPane scrollPane = new ScrollPane();
        // ScrollPane nimmt das Panel auf
        scrollPane.add(panel);

        frame.setContentPane(scrollPane);
        frame.pack();
        frame.setVisible(true);
    }

    class MyPanel extends JPanel {

        public MyPanel() {
            setPreferredSize(getDimension());
        }

        @Override
        protected void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;

            g2.setColor(Color.BLACK);
            for (Shape shape : shapes) {
                g2.fill(shape);
            }
        }
    }

    public static Shape getRectangle(int x, int y) {
        return new Rectangle2D.Double(x, y, 20, 20);
    }

    int getMaxWidth() {
        int width = FRAME_WIDTH;

        for (Shape shape : shapes) {
            if (shape.getBounds2D().getX() > width) {
                width = (int) shape.getBounds2D().getX();
            }
        }

        return width;
    }

    int getMaxHeight() {
        int height = FRAME_HEIGHT;
        for (Shape shape : shapes) {
            if (shape.getBounds2D().getY() > height) {
                height = (int) shape.getBounds2D().getY();
            }
        }
        return height;
    }

    Dimension getDimension() {
        return new Dimension(getMaxWidth(), getMaxHeight());
    }

}
```

Was du dann noch brauchst ist:

MouseListener und MouseMotionListener und das Verschieben zu registrieren und darauf zu reagieren
Ändern der Position für Shape's
Prüfung ob auf der Position ein Shape gibt und evtl. zurück geben
Verschieben von Shape's

Ändern der Dimension von ScrollPane
Neu Zeichnen
Prüfung ob Shape am Rand "aneckt"
Hoffe damit kannst du arbeiten. Du solltest dir natürlich überlegen, wie du das alles dann verwenden kannst.

Grüße


----------

