Bild an Bildschirmauflösung anpassen


#1

Hallo zusammen,

ich hätte eine Frage an euch bezüglich eines Splash Screens.

Ich habe eine Klasse erstellt, die von JFrame erbt, am Anfang habe ich ein JWindow verwendet.
Nur für ein JWindow gibt es die Methode “setExtendetState” nicht, was ich aber benötige da mein Programm auf jeden Rechner laufen soll.
Unterschiedliche Rechner gleich unterschiedliche Auflösungen
Deshalb habe ich ein JFrame verwendet und es undecorated gesetzt, funktioniert alles auch perfekt.
Nun habe ich ein .png Bild gezeichnet und zwar mit einer Auflösung von 4k.
Nun möchte ich dieses Bild auf einen 4k Fernseher darstellen können und natürlich auch auf einen normalen Laptop mit einer geringeren Auflösung.
Wie kann ich das Bild auf die Auflösung des jeweiligen Gerätes skalieren?
Das Bild wird mit einer Graphics g Methode also mit „g.drawImage“ gezeichnet, dass heißt ich muss mir zuerst einmal die Auflösung des Gerätes holen und anschließend das Bild an diese Größe anpassen, ohne das es unscharf wird.

Hat das einer von euch schon mal gemacht?

Ich bitte euch um Hilfe, da ich das nicht hinbekomme.

MfG


#2

Swing hat schon separate Splashscreen-Funktionalität, siehe https://docs.oracle.com/javase/tutorial/uiswing/misc/splashscreen.html

Die Bildschirmgröße bekommst du über:

GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();

Darauf musst du dein Bild halt skalieren.

Nebenbei bemerkt solltest du nicht von JFrame erben: http://wiki.byte-welt.net/wiki/Warum_man_nicht_von_JFrame/JDialog_erben_sollte


#3

Vermutlich wird es schon reichen, den Aufruf

g.drawImage(image, 0, 0, null);

zu ändern in

g.drawImage(image, 0, 0, getWidth(), getHeight(), null);

aber da müßte man natürlich mehr Code haben.


#4

Ich habe ein JFrame verwendet, da das JWindow die Methode setExtendedState(); nicht besitzt.

Mit: int height = gd.getDisplayMode().getHeight(); kann ich “height” in Size für das JWindow einsetzen.
Dann passt sich das Fenster immer an die Bildschirmauflösung an.

Ich werde das heute mal versuchen.

Vielen Dank!


#5

Hallo nochmals,

eine Frage noch, wie zeichnet ihr ein Bild auf ein JFrme bzw. JWindow.

Ich habe da jetzt das problem, dass das Bild garnicht mehr angezeigt wird.

public class StartScreen extends JWindow{

Image img;
GraphicsDevice t;

StartScreen() throws InterruptedException{
	
	t = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
	this.setSize(t.getDisplayMode().getWidth(), t.getDisplayMode().getHeight());

         this.setVisible(true);
	
     Thread.sleep(2000);
	
     this.dispose();
}
    public void paintComponent(Graphics g)
{
	img=Toolkit.getDefaultToolkit().getImage("Foto.png");
	g.drawImage(img, 0, 0, t.getDisplayMode().getWidth(), t.getDisplayMode().getHeight(), this);
}

Danach rufe ich diese Klasse in der Main auf, es kommt ein Fenster für zwei Sekunden aber das Bild bleibt aus.

Warum?


#6

In Swing muss man sich zumindest einmal darüber Informieren wie das ganze mit dem EventDispatchingThread richtig geht.

Im Moment so scheint es mir wird dein Constructor aufgerufen und angefangen abgearbeitet zu werden. Dann wird das mittels des Thread.sleep() unterbrochen und das halbfertige Fenster wird angezeigt.
Da der Constructor noch nicht am Ende ist, gibt es auch noch keinen Grund für den EDT das paintComponent aufzurufen. Höchstwahrscheinlich steht dieser ebenfalls. Irgendwann ist die Wartezeit vorbei, der Thread läuft weiter und das Dispose wird aufgerufen. Folglich hat man nur ein leeres Fenster gesehen.

Interessant ist was in der Main Methode steht, oder der Stelle die StartScreen initialisiert.

public static void main(String[] args) {
  StartScreen startScreen = null;
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      // Läuft im EDT
      startScreen = new StartScreen();
      startScreen.setVisible(true);
  });
  // Läuft im main-Thread
  Thread.sleep(2000);
  startScreen.setVisible(false);
}

Das kommt dann natürlich raus aus dem Constructor

this.setVisible(true);
Thread.sleep(2000);
this.dispose();

Man kann natürlich auch mit SwingWorkern arbeiten die aus dem Constructor heraus gestartet werden.
Zudem würde ich diese Zeile

img=Toolkit.getDefaultToolkit().getImage("Foto.png"); 

Nicht in der paintComponent Methode stehen haben, sondern im Constructor, da sonst bei jedem Neuzeichnen, warum auch immer das Bild neu von der Platte geholt werden würde, was unschöne Nebeneffekte hätte.


#7

Im Wiki gibt es zum Einbinden von Grafikdateien einen recht ausführlichen Artikel:
http://wiki.byte-welt.net/wiki/Grafikdateien_laden_und_anzeigen_(Java)


#8

Danke, es hat mit eurer Hilfe wunderbar geklappt.

Sorry, für die späte Antwort.

SG