2x JPanel im JScrollPane (Hintergrundbild in JScrollPane)

  • Themenstarter Themenstarter Gast
  • Beginndatum Beginndatum
Status
Nicht offen für weitere Antworten.
G

Gast

Gast
Hallo Leute,

ist es möglich - wenn ja wie - ein JScrollPane zu erstellen, dass wie gewöhnlich ein JPanel (mit Grafikinhalt) darstellen und scrollen kann, wobei hinter dem JPanel noch ein Hintergrundbild zu sehen sein soll (evtl. als JPanel), das nicht scrollbar ist?

Danke vor ab
 
paintComponent() der ScrollPane überschreiben und Hintergrundbild manuell einfügen. Könnte allerdings kompliziert werden.
 
interessantes Problem, das mag ich doch mal selber ausprobieren,
mit einigen setOpaque()-Aufrufen scheints zu gehen:

Code:
public class TestGUI
    extends JFrame
{

    public TestGUI()
        throws Exception
    {
        JPanel front = new FrontPanel();
        front.setPreferredSize(new Dimension(200, 1200));
        front.setOpaque(false);
        front.setBorder(BorderFactory.createLineBorder(Color.RED));

        JScrollPane scroll = new JScrollPane(front);
        scroll.getViewport().setOpaque(false);
        scroll.setOpaque(false);
        scroll.setBorder(BorderFactory.createLineBorder(Color.BLUE));

        JPanel back = new BackPanel();
        back.setBorder(BorderFactory.createLineBorder(Color.GREEN));
        back.setLayout(new BorderLayout());
        back.add(scroll);

        add(back);
        setSize(300, 300);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);

    }

    public static void main(String[] args)
        throws Exception
    {
        new TestGUI();
    }
}


class BackPanel
    extends JPanel
{

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        for (int i = 10; i < 200; i += 10)
        {
            g.drawArc(50, 50, i, i, 0, 360);
        }

    }

}


class FrontPanel
    extends JPanel
{

    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        for (int i = 10; i < 900; i += 100)
        {
            g.drawRect(40, i, 100, 30);
        }

    }

}
 
Also momentan habe ich noch eine Notfall-Lösung:
Ich erstelle einen Background-Panel auf dem ich den Zeichen-Panel platziere.
Dabei bettet JScrollPane den Zeichen-Panel ein und setzt den Viewport auf den Background-Panel.

Ich kann aber schlecht einschätzen, inwiefern 2 JPanels sich auf die effektive und schnelle Programmausführung auswirkt :/
 
Ich habe jetzt mal versucht SlaterB's Code auf meinen zu münzen. Allerdings will das Ganze noch nicht so richtig, wie ich es will. Das JScrollPane ist nicht sichtbar.
Irgendwas muss ich übersehen haben.
Hier der Code:

Die Klasse entspricht BackPanel:
Code:
public class JBackgroundPanel extends JPanel implements Constants {
    private static final Image nullImg = java.awt.Toolkit.getDefaultToolkit().getImage(PATH + "Images/Null-Layer [256x480].gif");
    
    public JBackgroundPanel() {
        this.setLayout(null);
        this.setPreferredSize(new Dimension(LEFT_SCROLLPANE_VP_WIDTH, LEFT_SCROLLPANE_VP_HEIGHT));
        this.setLocation(0, 0);
        this.setVisible(true);
    }
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponents(g);
        g.drawImage(nullImg, 0, 0, this);
    }
}

Die Klasse entspricht FrontPanel:

Code:
public class JLayerPanel extends JPanel implements Constants {
    private int         SCALE;
    private File        actualFile;
    private EditMapTab  upperCallingReference = null;
    private JGrid     grid;
    private TileMap  tileMap = null;
    
    public JLayerPanel(int scale, EditMapTab upperCallingReference) {
        this.SCALE                  = scale;
        this.upperCallingReference  = upperCallingReference;
        grid = new JGrid(8, 15, SCALE);
        this.setLayout(null);
        this.setPreferredSize(new Dimension(LEFT_SCROLLPANE_VP_WIDTH, LEFT_SCROLLPANE_VP_HEIGHT));
        this.setOpaque(false);
        this.setLocation(0,0);
        this.setVisible(true);
    }
public void setFile(File f) {
        this.actualFile = f;
        upperCallingReference.getZoomComboBox(0).setEnabled(true);
        try {
            this.tileMap = new TileMap(ImageIO.read(f), SCALE);
        } catch (IOException ex) {
            System.out.println("Fehler: Datei konnte nicht geladen werden.");
        }
        this.setPreferredSize(new Dimension(tileMap.getWidth()*16*SCALE, tileMap.getHeight()*16*SCALE));
        this.grid.setSize(tileMap.getWidth(), tileMap.getHeight());
    }
    
    public void setNullFile() {
        this.actualFile = null;
        tileMap = null;
        upperCallingReference.getZoomComboBox(0).setEnabled(false);
        setPreferredSize(new Dimension(LEFT_SCROLLPANE_VP_WIDTH, LEFT_SCROLLPANE_VP_HEIGHT));
    }
@Override
    public void paintComponent(Graphics g) {
        super.paintComponents(g);
        if (tileMap != null) {
            tileMap.draw(g);
        } else {
            g.drawImage(transpImg, 0, 0, this);
        }
        grid.draw(g);
    }

Und diese Klasse soll alles ausführen:

Code:
public class EditMapTab implements ActionListener, MouseListener, Constants, ScaleUpdating {
    public  int             SCALE           = 2;
    public  Tile            selectedTile    = null;

    private JBackgroundPanel bkgPanel       = new JBackgroundPanel();
    private JPaintBase      paintBase       = new JPaintBase(912, 512, this);
    private JLayerPanel     layerPanel      = new JLayerPanel(SCALE, this);

    private JPanel          leftFramePanel  = new JPanel();
    private JScrollPane     leftScrollPane  = new JScrollPane(layerPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);  
    private JButton         loadTilesetBtn  = new JButton("Set laden");
    private JButton         closeTilesetBtn = new JButton("Set schließen");
    
    
    public EditMapTab(JPanel callingReference) {
                
        leftScrollPane.setSize(LEFT_SCROLLPANE_VP_WIDTH + 20, LEFT_SCROLLPANE_VP_HEIGHT + 18);
        leftScrollPane.setLocation(8, 24);
        //leftScrollPane.getViewport().setView(layerPanel);
        leftScrollPane.getViewport().setOpaque(false);
        leftScrollPane.setOpaque(false);
        leftScrollPane.addMouseListener(this);
        leftScrollPane.setVisible(true);
        
        bkgPanel.add(leftScrollPane);
        
        loadTilesetBtn.setSize(112, 24);
        loadTilesetBtn.setLocation(22, 510);
        loadTilesetBtn.addActionListener(this);
        loadTilesetBtn.setVisible(true);
        
        closeTilesetBtn.setSize(112, 24);
        closeTilesetBtn.setLocation(158, 510);
        closeTilesetBtn.addActionListener(this);
        closeTilesetBtn.setVisible(true);
        
        leftFramePanel.setLayout(null);
        leftFramePanel.setSize(256+16+20, 480+24+40);
        leftFramePanel.setLocation(16, 48);
        leftFramePanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "TileViewer"));
        //leftFramePanel.add(leftScrollPane);
        leftFramePanel.add(bkgPanel);
        leftFramePanel.add(loadTilesetBtn);
        leftFramePanel.add(closeTilesetBtn);
        leftFramePanel.setVisible(true);
        
        callingReference.add(leftFramePanel);
        callingReference.add(toolbar);
    }
 
versuch doch erstmal ganz nochmal ein JScrollPane in dein BackPanel einzufügen,
ohne an die graphischen Finessen zu denken, und ohne so vielzusätzliches Zeug da reinzulegen..

in ein null-Layout kann man nur Komponenten mit setBounds
oder vielleicht auch setLocation + setSitze/ setPreferredSize einfügen,

erst wenn solche Grundlagen funktionieren, kann man über höheres nachdenken
 
Ohje ohje -.- Hier ist der Wurm drin. Ich habe jetzt mal versucht den null-LayoutManager außen vor zu lassen. Aber es wird im JScrollPanel der Hintergrund nicht angezeigt.

Hintergrund-Klasse:
Code:
public class JBackgroundPanel extends JPanel implements Constants {
    private static final Image nullImg = java.awt.Toolkit.getDefaultToolkit().getImage(PATH + "Images/Null-Layer [256x480].gif");
    
    public JBackgroundPanel() {
        
    }
    
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(nullImg, 0, 0, this);
    }
}

Vordergrund-Klasse:
Code:
public class JLayerPanel extends JPanel implements Constants, ScaleUpdating {
    private static final Image transpImg = java.awt.Toolkit.getDefaultToolkit().getImage(PATH + "Images/transp.gif");
    private int         SCALE;
    private File        actualFile;
    private EditMapTab  upperCallingReference   = null;
    private JGrid       grid;
    private TileMap     tileMap                 = null;
    
    public JLayerPanel(int scale, EditMapTab upperCallingReference) {
        this.SCALE                  = scale;
        this.upperCallingReference  = upperCallingReference;
        grid = new JGrid(8, 15, SCALE);
    }
    
    public void setFile(File f) {
        this.actualFile = f;
        upperCallingReference.getZoomComboBox(0).setEnabled(true);
        try {
            this.tileMap = new TileMap(ImageIO.read(f), SCALE);
        } catch (IOException ex) {
            System.out.println("Fehler: Datei konnte nicht geladen werden.");
        }
        this.setPreferredSize(new Dimension(tileMap.getWidth()*16*SCALE, tileMap.getHeight()*16*SCALE));
        this.grid.setSize(tileMap.getWidth(), tileMap.getHeight());
    }
    
    public void setNullFile() {
        this.actualFile = null;
        tileMap = null;
        upperCallingReference.getZoomComboBox(0).setEnabled(false);
        setPreferredSize(new Dimension(LEFT_SCROLLPANE_VP_WIDTH, LEFT_SCROLLPANE_VP_HEIGHT));
    }
    
    public Image getTileImageAt(int x, int y) {
        return tileMap.tile[x][y].img;
    }
    public Tile getTileAt(int x, int y) {
        return this.tileMap.tile[x][y];
    }
    public int getTileAtX(int x) {
        return Math.round(x/(16*SCALE));
    }
    public int getTileAtY(int y) {
        return Math.round(y/(16*SCALE));
    }
    
   
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponents(g);
        if (tileMap != null) {
            tileMap.draw(g);
        } else {
            g.drawImage(transpImg, 0, 0, this);
        }
        grid.draw(g);
    }
    
    @Override
    public void updateScale(int newScale) {
        this.SCALE = newScale;
        this.setFile(actualFile);
        tileMap.updateScale(newScale);
        tileMap.updateSet();
        grid.updateScale(newScale);
    }
}

Ausführende Klasse:
Code:
public EditMapTab(JPanel callingReference) {
        initToolBar();

        layerPanel.setPreferredSize(new Dimension(LEFT_SCROLLPANE_VP_WIDTH, LEFT_SCROLLPANE_VP_HEIGHT));
        layerPanel.setOpaque(false);
        
        leftScrollPane = new JScrollPane(layerPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);  
        leftScrollPane.setPreferredSize(new Dimension(LEFT_SCROLLPANE_VP_WIDTH + 20, LEFT_SCROLLPANE_VP_HEIGHT + 18));
        leftScrollPane.getViewport().setOpaque(false);
        leftScrollPane.setOpaque(false);
        
        bkgPanel.setLayout(new BorderLayout());
        bkgPanel.add(leftScrollPane);
        
        loadTilesetBtn.setPreferredSize(new Dimension(112, 24));
        loadTilesetBtn.setLocation(22, 510);
        loadTilesetBtn.addActionListener(this);
        loadTilesetBtn.setVisible(true);
        
        closeTilesetBtn.setSize(112, 24);
        closeTilesetBtn.setLocation(158, 510);
        closeTilesetBtn.addActionListener(this);
        closeTilesetBtn.setVisible(true);
        
        leftFramePanel.setSize(256+16+20, 480+24+40);
        leftFramePanel.setLocation(16, 48);
        leftFramePanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "TileViewer"));
        leftFramePanel.add(leftScrollPane);
        leftFramePanel.add(bkgPanel);
        leftFramePanel.add(loadTilesetBtn);
        leftFramePanel.add(closeTilesetBtn);
        leftFramePanel.setVisible(true);
        
        callingReference.add(leftFramePanel);
        callingReference.add(toolbar);
    }
 
mir fällt dazu nix ein,
bei einem kompletten Programm ließe sich natürlich alles kinderleicht korrigieren

falls du das posten magst, dann aber möglichst einfach,
Image painten sollte vielleicht drin sein,
aber ob ein Interface ScaleUpdating mit dem Problem zu tun hat, wage ich zu bezweifeln..
 
Okay, i did it!
Es fehlte noch für bkgPanel die Methode setPreferredSize().
Die brauchtest du natürlich bei deinen Grafikprimitiven nicht 🙂
Damit ist das Problem vom Tisch.
Danke für die Hilfe ^^
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben