Von Frame zu Frame "hangeln"

Havoc<>

Mitglied
Hallo zusammen,

ich soll ein Programm schreiben, dass eine Frage stellt, auf die Antwort wartet und dann eine neue Frage stellt. Jetzt habe ich mir vorgestellt, für jede Frage eine Class und darin einen Frame zu erstellen.

Siehe:

Code:
package sabine_project;
import javax.swing.*;

public class Sabine
{
  public static void main(String[] args)
  {
    Runnable runnable = new Runnable()
    {
      public void run()
      {
        Question1 q1Frame = new Question1();
        q1Frame.createAndShowGUI();
      }
    };
    SwingUtilities.invokeLater(runnable);
  }
}
Code:
package sabine_project;
import javax.swing.*;
import java.util.*;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.*;

public class Question1 extends JPanel implements ActionListener, KeyListener
{
  // globale Variabeln
  JLabel lPressed   = new JLabel("Nothing");
  JFrame startframe = new JFrame("Sabines Projekt");
  long   waited     = 0;
  //JLabel typepicture, adpicture, adpicture2, typepicture2 = new JLabel();
   
  public int createAndShowGUI()
  {
    // Programm beenden, nachdem das Fenster geschloßen wurde.
    startframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    startframe.setLocation(350,75);

    startframe.addKeyListener(this);

    // Panel anstatt kompliziertem ContentPane erstellen.
    JPanel anzeigePanel = new JPanel();
    anzeigePanel.addKeyListener(this);
    anzeigePanel.setLayout(new GridLayout(2, 3, 5, 5));
    
    JLabel typepicture = new JLabel();
    typepicture.setIcon(new ImageIcon("/home/jens/type_q.png"));
    typepicture.setAlignmentY(300);
    anzeigePanel.add(typepicture/*, BorderLayout.LINE_START*/);
    
    JLabel adpicture = new JLabel();
    adpicture.setIcon(new ImageIcon("/home/jens/testpic.png"));
    anzeigePanel.add(adpicture);
    
    JLabel typepicture2 = new JLabel();
    typepicture2.setIcon(new ImageIcon("/home/jens/type_a.png"));
    anzeigePanel.add(typepicture2);
    
    JLabel adpicture2 = new JLabel();
    adpicture2.setIcon(new ImageIcon("/home/jens/testpic.png"));
    anzeigePanel.add(adpicture2);
    
    lPressed.setText("Key");
    anzeigePanel.add(lPressed);

    // ContentPane des Frames zuletzt setzten.
    startframe.setContentPane(anzeigePanel);
    // Frame anzeigen.
    startframe.pack();
    startframe.setVisible(true);
    // Focus auf den Frame setzten.
    startframe.requestFocus();
    //anzeigePanel.requestFocus();
    
    // Zeit nach der anzeige holen...
    Date mytime = new Date();
    waited      = mytime.getTime();
    
    return 0;
  }

  public void keyTyped(KeyEvent e) 
  {
    String KeyChar = Character.toString(e.getKeyChar());
    lPressed.setText(KeyChar);
    if (KeyChar.equalsIgnoreCase("q"))
    {
      Date mytime2 = new Date();
      long gerechnet = ((mytime2.getTime() - waited));
    }
  }
  
  public void keyPressed(KeyEvent e) 
  {
    //lPressed.setText(Integer.toString(e.getID()));
  }

  public void keyReleased(KeyEvent e) 
  {
    //lPressed.setText(Integer.toString(e.getID()));
  }

  public void actionPerformed(ActionEvent e) 
  {
    System.exit(0);  
  }
}

Wenn ich jetzt eine weitere Class mit der Methode "createandshowGUI" erstellen würde, würde er wahrscheinlich beide Fenster gleichzeitig anzeigen.

Ich möchte aber, das erst die Frage beantwortet und dann das nächste Fenster geöffnet wird.

Versteht ihr was ich meine :-)?

Vielen dank!

Jens
 
Hallo,

wenn ich dir einen Vorschlag machen darf. Ich würde mir eine XML-Datei oder ähnliches mit den Fragen und Antworten machen, diese kannst du nachträglich ja immer wieder ändern ohne den Code ändern zu müssen.
Als nächstes würde ich mir ein allgmeines Question-Fenster machen, dem ich einfach die Frage als String übergebe. Ich denke mir, dass du dann Anwort-Möglichkeiten zur Verfügung stellst. Diese könntest du dem Fenster auch noch in einem Array oder einer ArrayList übergeben, in der Question-Fenster-Klasse kannst du ja dann überprüfen, ob es richtig ist oder nicht, bzw machen was du sonst noch willst.
Wenn du das Question-Fenster von JDialog ableitest und es Modal machst, dann läuft der Programm erst weiter, wenn das Fenster geschlossen wurde. So könntest du das ganze dann in einer Schleife oder ähnlichem laufen lassen.
Ich hoffe ich hab mich verständlich ausgedrückt.

MFG

zEriX
 
Hallo zerix,

danke für die Idee mit der XML. An sowas habe ich auch schon gedacht. Aber wie du an meinem Code oben wahrscheinlich unschwer erkennen kannst, bin ich recht neu in Java. In den paar Zeilen gibts wahrscheinlich 1000 Dingen zu optimieren.

Wie dem auch sei, ich muss das Programm relativ Zeitnah fertig bekommen :-). Deshalb ist mir das, als Java Neuling, mit XML erstmal zu "schwierig".

Das mit dem Dialog hört sich schonmal gar nicht schlecht an. Müsste ich dadurch viel verändern? Wie kann ich denn ein Fenster schließen? Mit "System.exit(0)" beende ich ja direkt das ganze Programm. Und "startframe.destroy/close" gibts irgendwie alles nicht :-).

Vielen dank schonmal für deinen Tipp.

Jens
 
Hallo erstmal !
Realisier das Ganze doch einfach durch eine Textdatei, aus der du pro Frage eine Zeile einließt. Das glaube ich wäre ein bischen einfacher als mit XML (zugegeben von XML habe ich auch keine Ahnung ;)).
Google mal nach Java+insel. Das Stichwort ist das Gallileo Open Book. Dort findest du Beispielcode und guute Erklärungen zum File-handling!!

Hier aber mal den Code um einen Dialog wieder verschwinden zu lassen !
Code:
dialogName.setVisible(false);
dialogname.dispose();

gruß

Gora
 
Java und insbesondere die Objektorientierung stehen auf wiederverwertbaren Code

nehmen wir einfach mal deinen code

Code:
package sabine_project;
import javax.swing.*;

public class Sabine
{
  public static void main(String[] args)
  {
    Runnable runnable = new Runnable()
    {
      public void run()
      {
        Question1 q1Frame = new Question1();
        q1Frame.createAndShowGUI();
      }
    };
    SwingUtilities.invokeLater(runnable);
  }
}

laut aufgabenbeschreibung wäre folgende struktur logischer (no so mal zum zeigen)


Code:
package sabine_project;
import javax.swing.*;

public class Sabine
{

int anzahlFragen=10;
final static int FRAGE=0,ANTWORT=1;
  public static void main(String[] args)
  {
    String[][] text = liessEin("datei.txt");
   for(int i =0;i<anzahlFragen;i++){
   Question q = new Question(text[i][FRAGE],text[i][ANTWORT]);
}
  }
}

wie du die fragen+antworten speicherst, als XML, CSV
oder einfach (1+2n).zeile Frage und (2+2n).zeile Antwort ist dabei egal


in deinem 2.Codesegment fehlt einfach der Knstruktor ;)

Code:
public Question (String frag,String ant){
this.TextfeldMitFrage.setText(frag);
this.antwort=ant;
}

der rest der klasse ist ja starr, den kann man so lassen, aber allein durch den Konstruktor, kann man die Klasse an jede Frage anpassen

hoffe das war nicht zu kompliziert dargestellt
 
Du musst ja nicht XML nehmen. Du könntest auch eine normale Text-Datei schreiben, die du dann mit nem FileInputStream und einem BufferedReader einliest. so kannst du dann Zeile für Zeile auslesen.
Der Vorteil für dich wäre so, dass du wesentlich weniger programmieren müsstest, du also schneller fertig wärst. Du kannst dann dein Programm auch viel leichter um Fragen erweitern.
Mit XML ist das gar nicht so schwer. Hier im Forum müsstest du eigentlich genug Beispiele finden. Du kannst aber auch hier nach schauen.
Ein Fenster "schließen" kannst du mir setVisible(false), bzw so ist es nicht mehr sichtbar und mit dispose(), werden dann alle Resourcen ans OS zurück gegeben.

MFG

zEriX
 
Vielen dank für die Zahlreichen Antworten :-).

Wahrscheinlich wäre das mit der Textdatei wirklich einfacher, aber es geht auch nicht zwangsläufig um Fragen. Sondern es geht um Psychologisches Kaufverhalten. Und zwar werden jeweils immer zwei Bilder angezeigt. Einmal von Markenprodukten und einmal von Nonameprodukten. Je nach dem, wie schnell der Bediener Antwortet (also entweder "q" oder "p" drückt) kann man vorhersagen ob er anfälliger für Markenprodukte oder Nonameprodukte ist.

Es geht also um Bilder die einer Taste zugeordnet werden und dann die Zeit von der Anzeige bis zum KeyEvent speichern. Ich könnte natürlich statt der Frage auch den Pfad zu den Bildern in eine XML/Textdatei schreiben, aber in meinem Fall (hoffe ich) kopier ich einfach die Klasse, passe den Pfad an und bin dann fertig.

Wenn das Projekt dann mehr anklang findet, kann ich es sicher noch mit XML überarbeiten.

Ich werde es jetzt erstmal mit dispose() versuchen. Vielen dank nochmal für die ganzen Antworten :-). Die ein oder andere Kleinigkeit lässt sich bestimmt auch noch verwerten.

Jens
 
Wenn du einen Rat annimmst, dann les dich ne Stunde (wenn überhaupt) in Dateiverarbeitung ein. Dann hast es nachher wesentlich einfachher. Vor allem da du in deinem Hauptprogramm, dann nur noch eine Klasse instanzieren musst und nicht soviele wie du bilder hast. So hast du im endeffekt wesentlich weniger arbeit, als wenn du alles kopierst und anpasst. Vor allem wirkt es wesentlich professioneller.
 
Um noch mal auf deine ursprüngliche Frage zurückzukommen und das aufzugreifen was zerix als letztes geschrieben hat (das scheinst du überlesen zu haben):
Du mußt nicht für jede Frage einen neuen Frame erzeugen. Du erstellst dir einmalig einen Frame in dem die beiden Bilder angezeigt werden. Nachdem der User eine Antwort getroffen hat, tauscht du die Bilder einfach aus. Dadurch mußt du keinen neuen Frame erzeugen, keinen alten schließen und arbeitest wesentlich performanter.

ein anderer Jens
 
Zurück