Background an Framegröße anpassen

Creepaz

Bekanntes Mitglied
Servus,

habe mal mein Hintergrundbild für mein Spiel soweit fertiggestellt, werde mich auch erst um alles andere kümmern. Würde aber gerne mal sehen wie es Ingame mit verschiedenen Monitorgrößen aussieht bevor ich das Backend anfange.

Ich habe einen JFrame, und dem möchte ich das Bild als Background einfügen. Das Bild hat eine Größe von 1920x1080 und soll sich eben an die Größe des Monitors anpassen. An meinem 23,5 Zoll geht es, auf meinem 17 Zoll wird nur noch gut die Hälfte angezeigt. Welche Möglichkeit gibt es, um es an dem Monitor anzupassen?

Vielen Dank im Vorraus.
 

mihe7

Top Contributor
An meinem 23,5 Zoll geht es, auf meinem 17 Zoll wird nur noch gut die Hälfte angezeigt.
Mit der Größe des Monitors hat das weniger zu tun als mit der Auflösung. Wenn Du ein 1920x1280 Bild auf einem 23,5"-Monitor anzeigst, der das Bild mit 1920x1280 auflöst nimmt das Bild den ganzen Bildschirm ein. Wenn Du das Bild auf einem 17"-Monitor anzeigst, der das Bild mit 1920x1280 auflöst, nimmt das Bild ebenfalls den ganzen Bildschirm ein.

Welche Möglichkeit gibt es, um es an dem Monitor anzupassen?

Ich verstehe die Frage nicht ganz. Du kannst
a) ein Bild mit möglichst passender Größe nehmen,
b) das Bild skalieren und
c) ein nicht-skaliertes Bild im Fenster platzieren.

Was und ggf. in welcher Kombination ist abhängig von Deinem Vorhaben. Willst Du z. B. dass das Bild einfach in das Fenster eingepasst wird: a) und b) (wenn Du nur ein Bild zur Verfügung hast, entfällt a) natürlich). Reicht es dagegen, wenn das Bild das Fenster ausfüllt, kann auch a) und c) verwendet werden. Möchtest Du, dass das Bild auf allen Geräten physikalisch halbwegs gleich groß erscheint? Dann musst Du ein Bild möglichst passender Größe anhand der Pixeldichte des Geräts skalieren und das Ergebnis im Fenster platzieren.
 

Creepaz

Bekanntes Mitglied
Mit der Größe des Monitors hat das weniger zu tun als mit der Auflösung. Wenn Du ein 1920x1280 Bild auf einem 23,5"-Monitor anzeigst, der das Bild mit 1920x1280 auflöst nimmt das Bild den ganzen Bildschirm ein. Wenn Du das Bild auf einem 17"-Monitor anzeigst, der das Bild mit 1920x1280 auflöst, nimmt das Bild ebenfalls den ganzen Bildschirm ein.



Ich verstehe die Frage nicht ganz. Du kannst
a) ein Bild mit möglichst passender Größe nehmen,
b) das Bild skalieren und
c) ein nicht-skaliertes Bild im Fenster platzieren.

Was und ggf. in welcher Kombination ist abhängig von Deinem Vorhaben. Willst Du z. B. dass das Bild einfach in das Fenster eingepasst wird: a) und b) (wenn Du nur ein Bild zur Verfügung hast, entfällt a) natürlich). Reicht es dagegen, wenn das Bild das Fenster ausfüllt, kann auch a) und c) verwendet werden. Möchtest Du, dass das Bild auf allen Geräten physikalisch halbwegs gleich groß erscheint? Dann musst Du ein Bild möglichst passender Größe anhand der Pixeldichte des Geräts skalieren und das Ergebnis im Fenster platzieren.
Danke dir für die konkrete Antwort. Was mein Vorhaben ist: Ich habe ein Bild erstellt, wie oben beschrieben. Und das soll der Spielhintergrund werden. Auf einer Auflösung mit 1920x1080 wird alles perfekt dargestellt, ich möchte aber, dass andere Auflösungen auch passend angezeigt werden. Sprich wenn jemand anders dieses Spiel öffnet mit z.B. 1080x720 das es dann auch passend dargestellt wird.
 

Creepaz

Bekanntes Mitglied
Ja, soweit habe ich es schon probiert. Hier mal mein Code soweit:

Java:
static BufferedImage bg;
 
 public Label() {
  try {
   bg = ImageIO.read((getClass().getResourceAsStream("(1) Spiellandschaft.png")));
  } catch (IOException e) {
   e.printStackTrace();
  }
  paintComponent(bg.createGraphics());
 }
 
 protected void paintComponent(Graphics g) {
     super.paintComponent(g);
     
     double scaleFactor = Math.min(1d, LoggedInPage.getScaleFactorToFit(new Dimension(bg.getWidth(), bg.getHeight()), getSize()));
     int scaleWidth = (int) Math.round(bg.getWidth() * scaleFactor);
     int scaleHeight = (int) Math.round(bg.getHeight() * scaleFactor);
     Image scaled = bg.getScaledInstance(scaleWidth, scaleHeight, Image.SCALE_SMOOTH);
     int width = getWidth() - 1;
     int height = getHeight() - 1;
     int x = (width - scaled.getWidth(this)) / 2;
     int y = (height - scaled.getHeight(this)) / 2;
     g.drawImage(scaled, x, y, FrameCreator.loggedIn);
 }

Kriege aber immer diesen Fehler:
Code:
Eception in thread "main" java.lang.IllegalArgumentException: Width (0) and height (0) must be non-zero
 
K

kneitzel

Gast
Was machst Du da? Dein Code macht einfach keinen Sinn!

Was Du da machst:
- Du erzeugst ein Buffered Image und lädst da ein Bild rein. (Soweit ok)
- Dann rufst Du paintComponent auf mit einem Graphics Objekt des Bildes?

=> Das Graphics Objekt dient dem "Malen" von Dingen. Somit erzeugst Du ein Graphics Objekt, mit dem Du in das Bild malen könntest. Wäre also super, wenn du auf das Bild noch was malen / schreiben wolltest. Aber damit veränderst Du das Bild und malst das Bild nicht irgendwo!

=> paintComponent wird nicht aufgerufen von Dir (Einfach als einfache Regel merken! Wenn Du im Detail weisst, was Du machst und Du tief im System eingreifen willst, dann ändert sich das evtl. mal, aber so am Anfang: never!). Das ist eine Funktion, die sozusagen vom System aufgerufen wird. Wenn Du willst, dass die Komponente irgendwas macht, dann kannst Du die paintComponent Funktion überschreiben um da dann irgendwas drin zu machen. Diese Funktion bekommt ein Graphics Object übergeben, welches die Komponente nutzen kann, um sich selbst zu malen.

Nebenbei: Was für Code zeigst Du da? Wenn es Deine Komponente ist, dann sollte das Bild nicht statisch sein!

Ansonsten sieht die überschriebene Funktion schon recht gut aus. Du berechnest aus bg ein scaled Image und das wird dann angezeigt. Zumindest auf den ersten Blick sieht das gut aus.

Notwendige Änderungen: Evtl. reicht es aus, wenn Du einfach den paintComponent Aufruf raus löschst. Dann wird das Bild beim erstellen vom Label geladen. Das Label, das Du erstellt hast, wirst Du ja irgendwo hinzufügen zu einem JFrame oder so ...
 

mihe7

Top Contributor
Ich würde aus Gründen der Geschwindigkeit zwei Bilder halten: das unskalierte und das skalierte und bei Größenänderungen der Komponente das skalierte Bild erzeugen, in paintComponent dann nur noch das skalierte Bild zeichnen. Also etwa so:

Java:
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

// for testing purposes
import javax.imageio.ImageIO;
import java.net.URL;

public class ImagePanel extends JPanel {
    private BufferedImage image;
    private Image scaled;

    public ImagePanel(BufferedImage image) {
        this.image = image;
    }

    @Override
    public Dimension getPreferredSize() {
        Insets insets = getInsets();
        int width = insets.left + insets.right + image.getWidth();
        int height = insets.top + insets.bottom + image.getHeight();
        return new Dimension(width, height);
    }

    @Override
    protected void paintComponent(Graphics g) {
        Insets insets = getInsets();
        g.drawImage(getScaled(), insets.left, insets.top, null);
    }

    private Image getScaled() {
        Insets insets = getInsets();                
        int w = getWidth() - insets.left - insets.right;
        int h = getHeight() - insets.top - insets.bottom;

        if (scaled == null || scaled.getWidth(null) != w || scaled.getHeight(null) != h) {
            scaled = image.getScaledInstance(w, h, Image.SCALE_SMOOTH);
        }

        return scaled;
    }


    public static void main(String[] args) throws Exception {
        BufferedImage img = ImageIO.read(new URL("https://upload.wikimedia.org/" +
                "wikipedia/commons/thumb/7/77/Wikipedia_svg_logo.svg/" +
                "768px-Wikipedia_svg_logo.svg.png"));

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.add(new ImagePanel(img));
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}
 

Creepaz

Bekanntes Mitglied
Habe nun mal das paintComponent entfernt, und über den PaintComponent-Teil ein @Override zum überschreiben. Allerdings wird dieser Teil trotzdem nicht ausgeführt.
 

Creepaz

Bekanntes Mitglied
Ich würde aus Gründen der Geschwindigkeit zwei Bilder halten: das unskalierte und das skalierte und bei Größenänderungen der Komponente das skalierte Bild erzeugen, in paintComponent dann nur noch das skalierte Bild zeichnen. Also etwa so:

Java:
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

// for testing purposes
import javax.imageio.ImageIO;
import java.net.URL;

public class ImagePanel extends JPanel {
    private BufferedImage image;
    private Image scaled;

    public ImagePanel(BufferedImage image) {
        this.image = image;
    }

    @Override
    public Dimension getPreferredSize() {
        Insets insets = getInsets();
        int width = insets.left + insets.right + image.getWidth();
        int height = insets.top + insets.bottom + image.getHeight();
        return new Dimension(width, height);
    }

    @Override
    protected void paintComponent(Graphics g) {
        Insets insets = getInsets();
        g.drawImage(getScaled(), insets.left, insets.top, null);
    }

    private Image getScaled() {
        Insets insets = getInsets();               
        int w = getWidth() - insets.left - insets.right;
        int h = getHeight() - insets.top - insets.bottom;

        if (scaled == null || scaled.getWidth(null) != w || scaled.getHeight(null) != h) {
            scaled = image.getScaledInstance(w, h, Image.SCALE_SMOOTH);
        }

        return scaled;
    }


    public static void main(String[] args) throws Exception {
        BufferedImage img = ImageIO.read(new URL("https://upload.wikimedia.org/" +
                "wikipedia/commons/thumb/7/77/Wikipedia_svg_logo.svg/" +
                "768px-Wikipedia_svg_logo.svg.png"));

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.add(new ImagePanel(img));
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}
Haut bei mir komischerweise nicht hin, kriege in der main Methode beim Laden des Bildes immer diesen Fehler:
Code:
Exception in thread "main" java.net.MalformedURLException: no protocol: resources/(1) Spiellandschaft.png
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Zurück Button -- Background wird nicht angezeigt Java Basics - Anfänger-Themen 4
F JLabel-Background Java Basics - Anfänger-Themen 7
A Frame Background Java Basics - Anfänger-Themen 21
Spin Background Image Java Basics - Anfänger-Themen 2
G PNG als Background Picture Java Basics - Anfänger-Themen 7
S Background von JtextField bei Focus in dem Feld ändern Java Basics - Anfänger-Themen 6
T Per Button row, cells der Tabelle farbigen Background geben Java Basics - Anfänger-Themen 6
M Wie bekomme ich einen Bild in einem JPaneln inden background Java Basics - Anfänger-Themen 3
JAVAnnik Framegröße Java Basics - Anfänger-Themen 5
A Framegröße nur in richtigen Proportionen ändern Java Basics - Anfänger-Themen 2
T User input in Verbindung mit ChronoUnit anpassen und falls falsche Eingabe getätigtwird Java Basics - Anfänger-Themen 7
J JScrollePane größe anpassen Java Basics - Anfänger-Themen 4
M Regex anpassen Java Basics - Anfänger-Themen 19
C Erste Schritte Layout an Bildschirmauflösung anpassen Java Basics - Anfänger-Themen 9
B String anpassen / maskieren Java Basics - Anfänger-Themen 3
L Doppelte Schleife Anpassen Java Basics - Anfänger-Themen 5
B Erste Schritte Objekte von JFrame der Fenstergröße anpassen Java Basics - Anfänger-Themen 3
N JButton anpassen Java Basics - Anfänger-Themen 3
D SQL Abfrage anpassen Java Basics - Anfänger-Themen 17
E Array-Größe anpassen Java Basics - Anfänger-Themen 1
E Input/Output Switch ausgabe anpassen bzw. anders darstellen Java Basics - Anfänger-Themen 13
D Koordinatensystem dynamisch anpassen Java Basics - Anfänger-Themen 17
T Kann erbende Klasse Attribute der vererbenden Klasse anpassen (int -> float)? Java Basics - Anfänger-Themen 9
G Erste Schritte Unter Mac "Path" anpassen .bash_profile? Java Basics - Anfänger-Themen 5
S Datei einlesen - Dateipfad unter Linux anpassen Java Basics - Anfänger-Themen 12
S 2D-Spiel im Vollbild an größe anpassen? Java Basics - Anfänger-Themen 3
M Spaltenbreite läßt sich nicht anpassen Java Basics - Anfänger-Themen 0
L JLabel Icon Größe anpassen Java Basics - Anfänger-Themen 11
K jlist an text anpassen Java Basics - Anfänger-Themen 3
J Dynamische Liste durchsuchen + anpassen Java Basics - Anfänger-Themen 3
L Jscrollpane nach zoomen anpassen Java Basics - Anfänger-Themen 20
M JTable nach erzeugung anpassen. Java Basics - Anfänger-Themen 4
H Höhe einer Komponente an Textinhalt anpassen Java Basics - Anfänger-Themen 4
B Maske an eine Matrix anpassen Java Basics - Anfänger-Themen 5
E JAVA Fortschrittsbalken an Methode anpassen? Java Basics - Anfänger-Themen 9
X JTable --> Spaltenbreiter am dargestellten Inhalt anpassen Java Basics - Anfänger-Themen 4
C JPanel Inhalt anpassen Java Basics - Anfänger-Themen 4
H Mac Menu-Über Programm anpassen Java Basics - Anfänger-Themen 3
D JPanel dynamisch anpassen Java Basics - Anfänger-Themen 5
D Bytes für WAV Format anpassen Java Basics - Anfänger-Themen 5
D Vererbung - Anpassen von Feldtypen!? Java Basics - Anfänger-Themen 6
M Links anpassen Java Basics - Anfänger-Themen 2
H JButtons anpassen Java Basics - Anfänger-Themen 3
M JSF/RichFaces anpassen? Java Basics - Anfänger-Themen 2
C Textgröße während des Programmlaufes anpassen Java Basics - Anfänger-Themen 6
G Button Größe anpassen Java Basics - Anfänger-Themen 4
N JTextfield anpassen Java Basics - Anfänger-Themen 2
R Arraygroesse dynamisch anpassen Java Basics - Anfänger-Themen 8
K .jpg JLabel anpassen Java Basics - Anfänger-Themen 3
C JTable Spaltenbreite anpassen Java Basics - Anfänger-Themen 9
L ImageIcon an jLabel anpassen? Java Basics - Anfänger-Themen 5
I Layout anpassen Java Basics - Anfänger-Themen 4
S Bild an Imagelabel anpassen Java Basics - Anfänger-Themen 4
G Spaltenbreite manuell anpassen bei einer JTable (wie bei.) Java Basics - Anfänger-Themen 13
M Spaltengrößen automatisch anpassen mit POI Bibliothek ? Java Basics - Anfänger-Themen 4
M Gezeichneten Text der Fenstergrösse anpassen Java Basics - Anfänger-Themen 2
G Anpassen einer JComboBox zur Laufzeit Java Basics - Anfänger-Themen 7
B JTextField dynamisch anpassen Java Basics - Anfänger-Themen 6
V GridLayout anpassen? Java Basics - Anfänger-Themen 6
F Tabellenspalten anpassen Java Basics - Anfänger-Themen 7
S Image von ImageIcon anpassen Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben