Problem mit JPopupMenu

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

Guest

Gast
Hallo!

Hab mir für einen JTree ein PopupMenu gemacht. Und je nachdem wie tief ich im Baum bin erscheinen andere Einträge im Menu. Als hab ich eine Eigene Klasse geschrieben an die ich nen ActionListener übergebe.

So jetz mein Problem:

Code:
/** ---- Ausschnitt aus meinem Programm ---- */
mi = new MenuItem("Buch entfernen");
mi.addActionListener(listener);
add(mi);
        
addSeparator();
        
mi = new MenuItem("Kapitel hinzufügen");
mi.addActionListener(listener);
add(mi);


Problem ist jetzt, dass das Menu nur auf den Zweiten Eintrag ("Kapitel hinzufügen") reagiert!
Ich denke mir, dass es vielleicht am listener liegt!? Aber ich hab den Code aus meinem Java_Buch, und nur leicht abgeändert... also, wo liegt das Problem???

tia,
Siris
 
Du musst immer wieder neue Instanzen eines MenuItems anlegen.
Wenn du jedesmal mit "mi" als Objektreferenz arbeitest, wird die davor erzeugte Instanz unbrauchbar, weil die Referenz nun auf ein anderes Objekt zeigt.
Also:
Code:
JMenuItem buchEntf = new JMenuItem("Buch entfernen");
JMenuItem kapitelNeu = new JMenuItem("Kapitel hinzufügen");
etc.

BTW: Bitte nicht den Fehler machen und Swing- mit AWT-Komponenten mischen, falls du das schon so gemacht hast.
 
L-ectron-X hat gesagt.:
Du musst immer wieder neue Instanzen eines MenuItems anlegen.
Wenn du jedesmal mit "mi" als Objektreferenz arbeitest, wird die davor erzeugte Instanz unbrauchbar, weil die Referenz nun auf ein anderes Objekt zeigt.
Also:
Code:
JMenuItem buchEntf = new JMenuItem("Buch entfernen");
JMenuItem kapitelNeu = new JMenuItem("Kapitel hinzufügen");
etc.

BTW: Bitte nicht den Fehler machen und Swing- mit AWT-Komponenten mischen, falls du das schon so gemacht hast.

OK thx, dass könnte sein ... ändere ich gleich.

Aber was meinst du mit dem Swing- mit AWT-Komponenten mischen?

tia
 
Gast hat gesagt.:
L-ectron-X hat gesagt.:
Du musst immer wieder neue Instanzen eines MenuItems anlegen.
Wenn du jedesmal mit "mi" als Objektreferenz arbeitest, wird die davor erzeugte Instanz unbrauchbar, weil die Referenz nun auf ein anderes Objekt zeigt.
Also:
Code:
JMenuItem buchEntf = new JMenuItem("Buch entfernen");
JMenuItem kapitelNeu = new JMenuItem("Kapitel hinzufügen");
etc.

BTW: Bitte nicht den Fehler machen und Swing- mit AWT-Komponenten mischen, falls du das schon so gemacht hast.
OK thx, dass könnte sein ... ändere ich gleich.

Edit: Hat nichts genützt, ist im Java-Buch ja auch so angeführt...

tia
 
Naja, ein JTree ist Swing, aber ein MenuItem ist AWT (das Pendant dazu in Swing wäre JMenuItem). In den FAQs steht auch was dazu, warum man die nicht mischen sollte.
 
ok, das mit swing und awt hab ich jetzt verstanden.

Aber kann mir keiner bezüglich des JPopupMenu helfen?

tia
 
wenns nicht an den menuitems liegt und du vermutest, dass es am actionlistener hängt, dann poste doch mal ein bissl code, denn hellsehen können wir hier noch nicht.
 
Code:
public class MyPopupMenu extends JPopupMenu 
{ 
  private ActionListener listener;
  
  /** Creates a new instance of MyPopupMenu */
  public MyPopupMenu(ActionListener listener)
  {    
    this.listener=listener;
  }
  
  public void setPopup(int pathCount) 
  { 
    JMenuItem mi;
    
    switch (pathCount)
    {     
      case 2:
      {
        mi = new JMenuItem("Buch entfernen");
        mi.addActionListener(listener);
        add(mi);
        
        addSeparator();
        
        mi = new JMenuItem("Kapitel hinzufügen");
        mi.addActionListener(listener);
        add(mi);        
      } break;
      case 3:
      {
        mi = new JMenuItem("Kapitel ändern");
        mi.addActionListener(listener);
        add(mi);
        
        mi = new JMenuItem("Kapitel entfernen");
        mi.addActionListener(listener);
        add(mi);
        
        addSeparator();
        
        mi = new JMenuItem("Thema hinzufügen");
        mi.addActionListener(listener);
        add(mi);       
      } break;
      case 4:
      {
        mi = new JMenuItem("Thema ändern");
        mi.addActionListener(listener);
        add(mi);
        
        mi = new JMenuItem("Thema entfernen");
        mi.addActionListener(listener);
        add(mi);        
      } break;
      default:
      {
        mi = new JMenuItem("Buch hinzufügen");
        mi.addActionListener(listener);
        add(mi);        
      }
    }
  }
}

Das is meine PopupMenu-Klasse.
Wenn noch mehr Code gebraucht wird, bitte einfach sagen.
 
Eingesetzt wird das JPopupMenu dann in meinem JTree

Code:
public class MyTree extends JTree implements ActionListener
{  
  /* ---- Tree-Attribute ---- */
  private DefaultMutableTreeNode nullRoot; 
  private DefaultMutableTreeNode root = new DefaultMutableTreeNode("Bücher");
  private DefaultTreeModel dtm;
  private TreePath tp;
  private TreePath tp2;
  
  /* ---- MyPopUpMenu ---- */
  private MyPopupMenu popup;
  
  private JFrame parent;
  
  /** Creates a new instance of MyTree */
  public MyTree(JFrame parent)
  {  
    this.parent=parent;
    
    setVisible(true);
    setBorder(new LineBorder(Color.BLACK,1));
    
    popup = new MyPopupMenu(this);
    add(popup);
    enableEvents(AWTEvent.MOUSE_EVENT_MASK);
    
    dtm = new DefaultTreeModel(root);
    this.setModel(dtm);
  }

  public void actionPerformed(ActionEvent e)
  {   
    if (e.getActionCommand().equals("Buch hinzufügen") ||
       (e.getActionCommand().equals("Kapitel hinzufügen")) ||
       (e.getActionCommand().equals("Thema hinzufügen")))
    {
      this.doSomethingWithChild(1);
    }     
    else if (e.getActionCommand().equals("Buch entfernen") ||
            (e.getActionCommand().equals("Kapitel entfernen")) ||
            (e.getActionCommand().equals("Thema entfernen")))
    {
      this.doSomethingWithChild(0);
    }
    else 
    {
      this.doSomethingWithChild(2);
    }
  }
  
  protected void processMouseEvent(MouseEvent e)
  {  
    if (e.getButton()!=e.BUTTON2)
    {
      tp2 = this.getSelectionPath();      
      tp = this.getPathForLocation(e.getX(),e.getY());
      if (tp != null)
      {
        this.setSelectionPath(tp);
        popup.removeAll();
        popup.setPopup(tp.getPathCount());
        
        if (e.isPopupTrigger()) 
        {      
          popup.show(e.getComponent(), e.getX(), e.getY());
        }
        super.processMouseEvent(e);
      }
      else 
      {
        this.setSelectionRow(-1);
      }
    }
  }
 
Code:
      case 2: 
      { 
        mi = new JMenuItem("Buch entfernen"); 
        mi.addActionListener(listener); 
        add(mi); 
        
        addSeparator(); 
        
        mi = new JMenuItem("Kapitel hinzufügen"); 
        mi.addActionListener(listener); 
        add(mi);        
      } break;
[...] //im weiteren Code so weitergeführt

Das kann so nicht gehen, weil du die Referenz "mi" immer auf ein neues Objekt zeigen lässt.
Es ist dann immer die letzte Zuweisung aktuell. Siehe meinen Post oben.
 
L-ectron-X hat gesagt.:
Code:
      case 2: 
      { 
        mi = new JMenuItem("Buch entfernen"); 
        mi.addActionListener(listener); 
        add(mi); 
        
        addSeparator(); 
        
        mi = new JMenuItem("Kapitel hinzufügen"); 
        mi.addActionListener(listener); 
        add(mi);        
      } break;
[...] //im weiteren Code so weitergeführt

Das kann so nicht gehen, weil du die Referenz "mi" immer auf ein neues Objekt zeigen lässt.
Es ist dann immer die letzte Zuweisung aktuell. Siehe meinen Post oben.

Ja, hat aber nichts bewirkt wie ichs geändert habe.
 
Anonymous hat gesagt.:
L-ectron-X hat gesagt.:
Code:
      case 2: 
      { 
        mi = new JMenuItem("Buch entfernen"); 
        mi.addActionListener(listener); 
        add(mi); 
        
        addSeparator(); 
        
        mi = new JMenuItem("Kapitel hinzufügen"); 
        mi.addActionListener(listener); 
        add(mi);        
      } break;
[...] //im weiteren Code so weitergeführt

Das kann so nicht gehen, weil du die Referenz "mi" immer auf ein neues Objekt zeigen lässt.
Es ist dann immer die letzte Zuweisung aktuell. Siehe meinen Post oben.

Ja, hat aber nichts bewirkt wie ichs geändert habe.

Ist ja auch klar:
Ich lass "mi" auf ein Objekt zeigen und füge es dann dem JPopupMenu hinzu. Dann lasse ich "mi" auf ein neues Objekt zeigen, füge es wieder dem JPopupMenu hinzu und so weiter und so fort...

Es ist also egal worauf das "mi" verweist...
 
Ist ja auch klar:
Ich lass "mi" auf ein Objekt zeigen und füge es dann dem JPopupMenu hinzu. Dann lasse ich "mi" auf ein neues Objekt zeigen, füge es wieder dem JPopupMenu hinzu und so weiter und so fort...

Es ist also egal worauf das "mi" verweist...
 
L-ectron-X hat gesagt.:
*Glaskugel raushol*
Keine Ahnung muss kaputt sein, kann nix sehen... :roll:

Was hast du wie geändert?

Ich habs geänder, gesehn dass es nichts bringt und wieder umgeändert :roll:


Noch was: Kann man irgendwie seine Posts editieren??
 
L-ectron-X hat gesagt.:
Anonymous hat gesagt.:
Es ist also egal worauf das "mi" verweist...

Verstehe ich jetzt nicht...
Was meinst du mit welcher Referenz und schließlich mit welchem Objekt nun der ActionListener arbeitet? Überleg mal.

Also mach ichs so:
Code:
switch (pathCount)
    {     
      case 2:
      {
        JMenuItem mi = new JMenuItem("Buch entfernen");
        mi.addActionListener(listener);
        add(mi);
        
        addSeparator();
        
        JMenuItem mi2 = new JMenuItem("Kapitel hinzufügen");
        mi2.addActionListener(listener);
        add(mi2);        
      } break;
      case 3:
      {
        JMenuItem mi3 = new JMenuItem("Kapitel ändern");
        mi3.addActionListener(listener);
        add(mi3);
        
        JMenuItem mi4 = new JMenuItem("Kapitel entfernen");
        mi4.addActionListener(listener);
        add(mi4);
        
        addSeparator();
        
        JMenuItem mi5 = new JMenuItem("Thema hinzufügen");
        mi5.addActionListener(listener);
        add(mi5);       
      } break;
      case 4:
      {
        JMenuItem mi6 = new JMenuItem("Thema ändern");
        mi6.addActionListener(listener);
        add(mi6);
        
        JMenuItem mi7 = new JMenuItem("Thema entfernen");
        mi7.addActionListener(listener);
        add(mi7);        
      } break;
      default:
      {
        JMenuItem mi8 = new JMenuItem("Buch hinzufügen");
        mi8.addActionListener(listener);
        add(mi8);        
      }
    }

Hab jetzt aber noch ein Problem, hab das PopupMenu in JPopupmenu und die MenuItems in JMenuItems umgeschrieben, und jetz werden die Items nur beim ersten Aufruf des Popup angezeigt, ansonsten wird das Popup zwar angezeigt, aber es sind kein MenuItems zu sehen ???:L
 
Mach die JMenuItems zu privaten Instanzvariablen.
Code:
public class Etwas extends Irgendwas {
  private JMenuItem buchEntf, kapitelNeu; //etc.
  [...]

  //irgendwo in einer Methode dann deine switch-Anweisung...
      case 2: 
      { 
        buchEntf = new JMenuItem("Buch entfernen"); 
        buchEntf.addActionListener(listener); 
        add(buchEntf); 
        
        addSeparator(); 
        
        kapitelNeu = new JMenuItem("Kapitel hinzufügen"); 
        kapitelNeu.addActionListener(listener); 
        add(kapitelNeu);        
      } break; 
   
      case 2:
      [...] //etc. pp.

Was ist eigentlich mit case 1?
 
Ok, danke, funktioniert jetzt! Versteh nicht ganz warum, aber es funktioniert.

Einziges Problem is noch, dass wie oben beschrieben die JMenuItems nur beim ersten mal auftauchen.
 
L-ectron-X hat gesagt.:
Lässt sich ohne Code auch nicht zweifelsfrei klären...

Mit dem Code vom JPopup und dem JTree, wo das JPopup eingesetzt wird, wirds doch gehn, oder?
Oder von welcher Klasse bräuchtest du den Code noch??

tia
 
Sollte für den Anfang genügen, ja.
Falls du die Events für das JPopupMenu und den JTree in extra Klassen ausgelagert hast, sind die auch noch interessant.
 
L-ectron-X hat gesagt.:
Sollte für den Anfang genügen, ja.
Falls du die Events für das JPopupMenu und den JTree in extra Klassen ausgelagert hast, sind die auch noch interessant.

Hab ich nicht...

Nochmal zum Problem:
Also, das Popup hat funktioniert, mit den MenuItems! Dann hab ich auf JPopupMenu und JMenuItem umgeschreiben, und jetzt werden die JmenuItems nur beim ersten Aufruf angezeigt, bei allen weiteren, ist es so, dass sich das JPopupMenu öffnet und genau die gewünschte Größe für die gewünschte Anzahl an JMenuItems hat, nur sind die JMenuItems irgenwie "unsichtbar" ???:L

Naja, vielleicht weißt du ja was, ich kanns mir irgendwie nicht erklären...

tia
 
Das einzige, was mir erstmal (ohne Code zu sehen) einfällt ist, dass vielleicht irgendwo noch Swing- mit AWT-GUI-Komponenten gemischt sein könnten.
 
L-ectron-X hat gesagt.:
Das einzige, was mir erstmal (ohne Code zu sehen) einfällt ist, dass vielleicht irgendwo noch Swing- mit AWT-GUI-Komponenten gemischt sein könnten.
Find ich nichts, ist mir irgendwie ein Rätsel, total unlogisch...
 
L-ectron-X hat gesagt.:
Tja, ich finde auch nix... :roll:
*Glaskugel wieder wegsteck*

Ich hab jetzt die ganzen Swing-Elemente (JPopupMenu, JMenuItem) wieder in AWT geändert, und das komische ist, dass es mit den AWT-Elementen geht ... ich verändere ansonsten nichts am code, es liegt also einfach nur daran, dass es einmal Swing und einmal AWT ist !!??

Wenn dir dazu vielleicht noch was einfällt...

Ansonsten, danke für deine Hilfe!

mfg
 
Noch was: Ich hab jetzt gemerkt, dass wenn ichs mit Swing mach, dann werden, wenn ich ganz oft klicke, zwischendurch die JMenuItems sichtbar !!!!????

Also das versteh ich nun wirklich nicht mehr ...
 
OK, habs jetzt! ENDLICH!
Der Fehler wahr der, dass ich beim processMouseEvent kein neues Popup erstellt hab, sondern immer nur die Methode setPopup aufgerufen hab und dort die Position im Baum übergeben hab!

Ich weiß zwar nicht wie das mit den AWT Elementen gehen konnte, aber naja...

Danke für eure Hilfe!
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben