kostenloser Webspace werbefrei: lima-city


"Framebuffer" bei Swing

lima-cityForumProgrammiersprachenJava

  1. Autor dieses Themas

    cain916

    cain916 hat kostenlosen Webspace.

    Hallo,

    ich weiß nicht ob Frambuffer der richtige Ausdruck ist, aber ich habe folgendes Problem: Ich habe ein Programm geschrieben das, vereinfacht gesagt etwas in ein Fenster malt. Allerdings habe ich das Problem, dass der Inhalt jedes mal gelöscht wird, wenn das Fenster von einem anderem Fenster überdeckt wird. D.h. der Fensterinhalt ist danach grau und der Inhalt ist verloren.
    Ich kenne mich mit Swing nicht so genau aus, aber ich habe schon gehört dass es da so etwas wie ein JPanel gibt, das ich nicht verwendet habe. Liegt es vielleicht daran?
    Der Code schaut in etwa so aus:

    ....
    ....
    	private static JFrame fenster = new JFrame("Fenster");
    	private static JTextField txt = new JTextField("Textfeld");
    	private static Button zurueck = new Button("<--");
    	private static Button vor = new Button("-->");
    
    	public static void main(String[] args) {
                    fenster.add(zurueck);
    		fenster.add(txt);
    		fenster.add(vor);
    		fenster.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 5));
                   fenster.setSize(600, 600);
                   fenster.setVisible(true);
                   fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                   fenster.setResizable(false);
    		paint(fenster.getGraphics());
    	}
    
           public static void paint(Graphics g) {
    		ImageIcon ico = new ImageIcon(Reader.class.getResource("bild.jpg"));
    		ImageObserver imgo = null;
    		g.drawImage(ico.getImage(), 5, 3, 500, 500, imgo);
    	        g.drawString("String",5,5);
    ...
    ...
          }


    Wäre toll wenn jemandem dazu etwas einfällt.

  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. e********l

    Öhm, was willst du denn bezwecken?

    Das Image würde ich direkt als Image Component dem Frame hinzufügen und den Text über ein JLaben einbinden.

    Und das der Inhalt verloren ist kann eigentlich nur daran liegen, das die Paint Methode von deinem Frame nur aufgerufen wird, wenn es auch aktiv ist. Mal davon abgesehen das dein Code den GC ganz stark belastet.
  4. Moin,

    also erst einmal: Sehr schlechter Code, da alles statisch gehalten wird.
    Versuche das ganze mit Objekten zu lösen ... Code folgt, aber erst ein paar Erklärungen:

    Mit Objekten meine ich, dass Du den ganzen Aufbau "verteilst", sprich ein JFrame und ein JPanel wo draufgezeichnet wird.
    Wenn Du mit Swing-Komponenten arbeitest, wird eher empfohlen, die paintComponent()-Methode zu überschreiben, anstatt die paint()-Methode.

    Außerdem musst Du zu Beginn der paintComponent-Methode bzw. der paint-Methode super aufrufen.

    Nachfolgend der Code, wie - zumindest ich - es am übersichtlichsten finde.
    Besonders die Abgrenzung zwischen Swing-Elementen und einfließenden anderen Komponenten wie z.B. Bildern.

    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    
    import javax.swing.ImageIcon;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    public class ImageFrame extends JFrame {
        private ImagePanel imagePanel;
    
        public ImageFrame() {
            imagePanel = new ImagePanel();
            init();
        }
    
        public void init() {
            this.setTitle("ImageFrame");
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
            this.setSize(300, 300);
            this.setResizable(false);
            this.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 5));
            this.add(imagePanel);
            this.setVisible(true);
        }
    
        public static void main(String[] args) {
            new ImageFrame();
        }
    }
    
    
    class ImagePanel extends JPanel {
        private ImageObserver imgo = null;
        private ImageIcon     ico;
    
        public ImagePanel() {
            ico = new ImageIcon(Reader.class.getResource("bild.jpg"));
            init();
        }
    
        public void init() {
            this.setPreferredSize(new Dimension(50, 50));
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(ico.getImage(), 5, 3, 500, 500, null);
            //g.drawString("String", 3, 10); - rausgenommen
        }
    }

    Edit:
    @ evil:
    Klar, warum auch nicht alles direkt über Komponenten lösen, wäre einfacher.
    Aber da das System hinter dem Zeichnen dann eventuell nicht verstanden ist, hab ich's mal komplexer dargestellt *g*

    Gruß,
    Pawnee

    Beitrag zuletzt geändert: 4.6.2009 16:20:57 von pawnee
  5. e********l

    Darum hab ich ja gefragt was seine Intentionen sind. Vielleicht will er ein Game schreiben...dann sollte er im Idealfall gleich von Canvas erben und jenes Canvas einem Frame adden ^^
  6. Autor dieses Themas

    cain916

    cain916 hat kostenlosen Webspace.

    Danke erstmal für die Antworten.
    Dass der Code nicht besonders gut ist wundert mich nicht; es ist mein erster Versuch sowas in der Art zu machen.
    Das Programm soll in Prinzip sowas wie ein digitales Buch sein. Also Text aus einer Datei lesen und entsprechend formatiert anzeigen auf Knopfdruck dann zur nächsten Seite "blätter", also alter Text weg und neuer Text hin. Dazu dann noch ein Hintergrundbild.
    Ich werde dann heute Nachmittag versuchen das ganze ein bißchen umzuarbeiten nach der Vorlage von pawnee.


    edit:
    Scheint soweit zu klappen. Danke dafür. Eine Frage hab ich aber noch: Wie kann ich die Methode ImagePanel.paintComponent(Graphics) aufrufen. Zum Beispiel vom ActionListener eines Buttons aus (Seite soll "umgeblättert" werden, und damit alter Text weg und neuer hin). Der Aufruf an sich ist ja kein Problem, aber ich muß ja auch noch das Argument Graphics übergeben. Woher kommt das?

    mfg

    Beitrag zuletzt geändert: 5.6.2009 17:28:10 von cain916
  7. Moin,

    die Methode selbst rufst Du dabei gar nicht auf.
    Dafür steht Dir die repaint() Methode zur Verfügung, die alles, was in paint() bzw. paintComponent() durchgespielt wird, noch einmal wiederholt.

    Gruß,
    Pawnee
  8. Autor dieses Themas

    cain916

    cain916 hat kostenlosen Webspace.

    Ok. Ich glaube ich nähere mich so langsam dem Ziel. Ich habe aber immer noch nichtt ganz kappiert was es mit dem static auf sich hat. Ich rufe z.B. die repaint()-Methode auf: ImageFrame.imagePanel.repaint(); und dann sagt mir eclipse "Cannot make a static reference to the non-static field ImageFrame.imagePanel". Jetzt habe ich einfach mal bei der Deklaration von imagePanel ein static mit reingemacht. Dann klappt die Sache, allerdings hast du doch am Anfang gemeint, dass zu viel statisches nicht gut sei?
    Ein ähnliches Problem habe ich noch einmal: Ich will die Methode setzteTitel(String titel) aufrufen:

    public class ImageFrame extends JFrame {
          
        public static ImagePanel imagePanel;   //public und static ergänzt damit repaint() klappt
    
        public ImageFrame() {.... }
    
        public void init() {... }
         
        public void setzteTitel(String titel) {
        	this.setTitle(titel);
        }
    
        public static void main(String[] args) {...}
    }


    Wenn ich jetzt von meinem Hauptprogramm aus ImageFrame.setzteTitel("blablabla") aufrufe, meldet mir Eclipse auch das gleiche. Wenn ich die Methode auch statisch deklariere kann ich "this" nicht mehr benutzten.
  9. Moin,

    kannst Du mal Deinen derzeitigen kompletten Code zeigen bitte?
    Aber nutze bitte http://pastebin.com dafür und gib den Link an.
    Ist um einiges übersichtlicher - da man auf die Zeilen verweisen kann.

    Gruß,
    Pawnee
  10. h*****b

    Die Fehlermeldung bedeutet auf alle Fälle, dass eine Methode oder ein Objekt static, also auch ohne Erstellung eines Objekts dieser Klasse verfügbar, ist. Du versuchts jetzt aber mit einer statischen (also static-)Methode, auf ein nicht-statisches Objekt zuzugreifen, welches nicht existiert. Aber wie gesagt: Für genaueres brauchen wir den Quellcode.

    mfg
    htnipdb
  11. Autor dieses Themas

    cain916

    cain916 hat kostenlosen Webspace.

    OK.
    Gesamtcode gibts hier: http://pastebin.com/m2d222b14
    Ich hoffe ihr blickt halbwegs durch. Ich kann mir vorstellen, dass das ganze noch besonders "schön" ist, aber besser sind meine Fähigkeiten leider nicht...
    Das Problem was ich vorher gemeint habe ist in Zeile 130ff. Alles was unten drunter kommt ist denk ich mal nicht so wichtig. Das läuft so wie es soll.
  12. Phuuuu,

    also ehrlich gesagt habe ich erstmal nen Schock bekommen, als ich das gesehen habe.
    Um es noch einmal deutlich zu machen:
    Lass den statischen Kram da raus, wenn er nicht UNBEDINGT notwendig ist.

    Erklärung zu static:
    Wenn ein Element mit static definiert ist, dann kannst Du dieses per Klasse.element (sei es Attribut oder Methode) aufrufen.
    Das heißt, Du benötigst in diesem Fall keine Instanz der Klasse, sondern greifst direkt auf das Element zu.

    Beispiel:
    public class Klasse {
        public static int NUMMER = 1;
    
        public static double rundeZahl(double zahl) {
            return Math.round(zahl * 10) / 10.0;
        }
    }
    
    public class AndereKlasse {
        public static void main(String[] args) {
            System.out.println(Klasse.rundeZahl(12.2388283));    // direkter Zugriff auf die Methode
            System.out.println(Klasse.NUMMER);                   // direkter Zugriff auf die Variable
        }
    }

    Erklärung zu non-static:
    "Nicht-statische" Elemente erfordern das Erzeugen einer Instanz der Klasse, von der aus das Element aufgerufen werden soll.
    Eine Erzeugung erfolgt durch den new Operator - siehe nachfolgende main-Methode.

    Beispiel:
    public class Klasse {
        private int nummer;    // nur Deklaration
    
        public Klasse() {
            this.nummer = 1;    // Initialisierung innerhalb des Konstruktors
        }
    
        public double rundeZahl(double zahl) {
            return Math.round(zahl * 10) / 10.0;
        }
    
        public int gibNummer() {
            return nummer;
        }
    }
    
    public class AndereKlasse {
        public static void main(String[] args) {
            Klasse klasse = new Klasse();    // Erzeugung einer Instanz
    
            // Aufruf der Methode aus Klasse, da klasse auf deren Instanz referenziert
            System.out.println(klasse.rundeZahl(12.2388283));
            System.out.println(klasse.gibNummer());
        }
    }

    Und da Dein gesamter Code so ziemlich statisch aufgebaut ist, kriegst Du jedes Mal diese Fehlermeldung, dass sich beides nicht miteinander verträgt.
    Also mache nur das Wichtigste statisch (z.B. HOEHE, BREITE, RANDOBEN) und der Rest sollte über das Objekt verwaltet werden.

    Gruß,
    Pawnee
  13. Autor dieses Themas

    cain916

    cain916 hat kostenlosen Webspace.

    So. Ich habe jetzt so ziemlich alles statische entfernt (außer den Variablen, die sich während des kompletten Programmablaufs nicht ändern, eig. nur die Größenangaben...) Ich denke das Konzept habe ich auch so in etwas kapiert. Auch was der Sinn von get und set Methoden ist, die ich jetzt gebraucht habe. Wenn ich wieder mal was schreibe, dann werde ich dran denken.
    Ich habe halt am Anfang angefangen von der (statischen) main-Methode ausgehend das Programm aufzubauen. Als Folge musste der ganze Rest eben auch statisch sein...
    Durch den Umbau haben sich dann auch alle andren Probleme die ich hatte gelöst.
    Danke noch mal für die Hilfe!

    mfg

    Beitrag zuletzt geändert: 6.6.2009 18:34:13 von cain916
  14. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!