JTabbedPane per Menuitem erstellen

plammy

Bekanntes Mitglied
Hallo 🙂
Ich hab folgendes Problem: Ich erstelle per MenuItem Neu... ein JPanel, der sich in einem scrollable TabbedPane befindet. Ich will, dass jedes mal wenn ich auf Neu.. drücke ein zusätzliches JTabbedPane neben den schon bestehenden hinzugefügt wird. Im Moment erscheint aber immer nur ein. Ich will das quasi wie bei Photoshop oder ähnliche Programme, dass wenn man neue Datei erstellt sich immer wieder ein neuen Tab öffnet wo man arbeiten kann.

Java:
public class GUI extends JFrame implements ActionListener {

 
    /**
     * Erstelle neue GUI
     */
    public GUI() {

        initComponents();   

        setTitle("Layout Tool");
        setSize(900,980);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
       
    }

 public void initComponents() {
        menubar = new JMenuBar();
        menuFile = new JMenu();
        neu = new JMenuItem();

        neu.setMnemonic(KeyEvent.VK_N);
        neu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
        neu.setText("Neu");
        neu.addActionListener(this);
        menuFile.add(neu);
....
}
    public void actionPerformed(ActionEvent object) {
       
        
        //Neu
        if (object.getSource() == neu){     
             CreateFile create = new CreateFile();   
             create.addTabbedPane();
             setContentPane(create);    
             setVisible(true);
        }
.....

Java:
public class CreateFile extends JPanel implements ActionListener
{
 public CreateFile()
    {
        initComponents();    
        buildLayout();
    }

 public void addTabbedPane(){
        scrollPane.setViewportView(editPanel);
        tabbedPane.addTab("Tab "+this.COUNTER ,scrollPane);
        this.COUNTER++;
    }

 public void buildLayout(){
        buildWebsitePanel();
        buildLayoutPanel();
        buildfixFormsPanel();
        buildIndividualFormsPanel();
        buildOrangeFormsPanel();
        buildEditPanel(); 
        buildHolePanel();
    } 

...

 public void buildHolePanel(){

        GroupLayout layout = new GroupLayout(this);
        this.setLayout(layout);
        this.setBackground(darkGray);
        layout.setHorizontalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
              
                .addComponent(tabbedPane, GroupLayout.DEFAULT_SIZE,0, Short.MAX_VALUE)
                .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
                    .addComponent(websitePanel, GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(layoutPanel, GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(fixFormsPanel, GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(individualFormsPanel, GroupLayout.DEFAULT_SIZE,0, Short.MAX_VALUE)
                    .addComponent(orangeFormsPanel, GroupLayout.DEFAULT_SIZE,0, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(20 , 20, 20)
                .addComponent(websitePanel)
                .addGap(18, 18, 18)
                .addComponent(layoutPanel)
                .addGap(18, 18, 18)
                .addComponent(fixFormsPanel)
                .addGap(18, 18, 18)
                .addComponent(individualFormsPanel)
                .addGap(18, 18, 18)
                .addComponent(orangeFormsPanel)
                .addContainerGap())
                
            .addComponent(tabbedPane)            
        );  
    
    }
 
Habe deinen Code nur überflogen.
Kann sein, dass du noch
Code:
validate();
aufrufen musst, damit die Oberfläche neu gezeichnet wird.
 
Gut, dann hier mal ein Beispiel:
Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TabbedAdder implements ActionListener {
  private JTabbedPane pane;
  private JMenuItem fileMenuItem;
  
  public TabbedAdder() {
    JFrame frame = new JFrame("JTabbedPane - Tabs hinzufügen");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(800, 600);
    frame.setLocationRelativeTo(null);
    frame.setJMenuBar(createTheMenuBar());
    frame.add(createThePane());
    frame.setVisible(true);
  }
  
  private JTabbedPane createThePane() {
    pane = new JTabbedPane();
    return pane;
  }
  
  private JMenuBar createTheMenuBar() {
    JMenuBar bar = new JMenuBar();
    JMenu file = new JMenu("Datei");
    fileMenuItem = new JMenuItem("Neu");
    fileMenuItem.addActionListener(this);
    file.add(fileMenuItem);
    bar.add(file);
    return bar;
  }
  
  public void actionPerformed(ActionEvent e) {
    pane.add("Unbenannt-"+(pane.getTabCount()+1), new JPanel());
    pane.setSelectedIndex(pane.getTabCount()-1);
  }
    
  public static void main(String[] args) {
    TabbedAdder ta = new TabbedAdder();
  }
}
 
Ich habs versucht das in meinem Code umzusetzten, aber ich hab anscheinend iwo ein Denkfehler... 🙁.. Funktioniert immer noch wie früher




Java:
public class GUI extends JFrame implements ActionListener {

 
    /**
     * Erstelle neue GUI
     */
    public GUI() {

        initComponents();   

        setTitle("Layout Tool");
        setSize(900,980);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);      
    }
..
 public void actionPerformed(ActionEvent object) {
       
        
        //Neu
        if (object.getSource() == neu){     
              
        CreateFile create = new CreateFile();   
        create.deleteTF();
        create.tabbedPane.add("Tab "+(create.tabbedPane.getTabCount()+1) ,create.scrollPane);
        validate();
        setContentPane(create);    
        setVisible(true);
        }


Java:
public class CreateFile extends JPanel implements ActionListener
{
  public CreateFile()
    {  
        addTabbedPane();
        initComponents();    
        buildLayout();
      
    }
..
  public ClosableTabbedPane addTabbedPane(){
         //Panels 
        tabbedPane = new ClosableTabbedPane();
        
        editPanel = new EditPanel();
        editPanel.setFocusable(true);           
        editPanel.getPreferredSize();

        scrollPane=new JScrollPane();
        scrollPane.setFocusable(true);
        scrollPane.setPreferredSize(new Dimension(600,600));  //sichtbare Größe der ScrollPane 
        
        scrollPane.setViewportView(editPanel);
       
        
        return tabbedPane;
    }
 
scrollPane.setPreferredSize(new Dimension(600,600)); //sichtbare Größe der ScrollPane

ist schonmal ein zeichen für ein schlechtes Layoutkonzept.

Java:
public class DieTabbedPane extends JTabbedPane{
	
	public void neuesTab(String titel, JPanel inhalt){
		this.addTab(titel, inhalt);
	}

}
...sollte eigentlich all das tun, was du wolltest.
Ein validate(); hab ich bisher nie benötigt.

Gruß Vanny
 
Dein Kontrukt/Klassendesign ist merkwürdig.
Gründsätzlich fragwürdig ist warum, um eine neue Tab hinzuzufügen, jedesmal ein neues Objekt (CreateFile) erzeugt wird, das scheinbar diesen Hinzufügen vornehmen soll?
Auch das Erzeugen einer neuen ClosableTabbedPane Instanz ist merkwürdig - mal abgesehen, davon, dass damit scheinbar nichts gemacht wird. Gründsätzlich stehen im Code - zumindest in dem hier geposteten - viele nutzlose Zeilen.

Allgemein: Definiere eine Klasse, welche die Inhalte der JTabbedPane kontrolliert und das Hinzufügen/Entfernen von Tabs steuert.
 
ja aber das problem ist dass ich GroupLayout verwende und nicht einfach frame.add(pane) sagen kann...
Was hat das mit dem GroupLayout und dem Frame zu tun? Es sollen doch während der Laufzeit Tabs in einer bestehenden JTabbedPane hinzugefügt bzw. entfernt werden - und das geht ja direkt an der JTabbedPane mit addTab(...) bzw. removeTabAt(int)
 
ja aber wo soll ich das denn schreiben??? es geht nicht egal wo ich das mach 🙁

Allgemein: Definiere eine Klasse, welche die Inhalte der JTabbedPane kontrolliert und das Hinzufügen/Entfernen von Tabs steuert.

Dafür habe ich ja meine Klasse ClosableTabbedPane

Java:
public class ClosableTabbedPane extends JTabbedPane{
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private TabCloseUI closeUI = new TabCloseUI(this);
        GUI gui = new GUI();
        
    @Override
        public void paint(Graphics g){
                super.paint(g);
                closeUI.paint(g);
        }
        
    @Override
        public void addTab(String title, Component component) {
                super.addTab(title+"  ", component);
        }
        
        
        public String getTabTitleAt(int index) {
                return super.getTitleAt(index).trim();
        }
        
        private class TabCloseUI implements MouseListener, MouseMotionListener {
                private ClosableTabbedPane  tabbedPane;
                private int closeX = 0 ,closeY = 0, meX = 0, meY = 0;
                private int selectedTab;
                private final int  width = 5, height = 5;
                private Rectangle rectangle = new Rectangle(0,0,width, height);
                @SuppressWarnings("unused")
                private TabCloseUI(){}
                
                
                public TabCloseUI(ClosableTabbedPane pane) {
                        
                        tabbedPane = pane;
                        tabbedPane.addMouseMotionListener(this);
                        tabbedPane.addMouseListener(this);
                }
                ....
}
 
Zuletzt bearbeitet:
MouseListener eine paint() Methode hat

was meinst du damit?

Also ich versuchs das ganze neu zu erklären 🙂

Ich habe 2 Klassen: CreateFile und GUI
in GUI werden die Menüs erzeugt und das Startpanel erzeugt.
Wenn man z.b.der Menüeintrag "New" anklickt, soll einen neuen JPanel an der Stelle von startPanel erzeugt werden, und dieser neuen JPanel wird in CreateFile definiert(also alles was dadrin stehen muss und gezeichnet wird und layout und bla). In diesen neuen JPanel ist auch die JTabbedPane.
 
was meinst du damit?
Das Bezog sich auf die Klasse TabCloseUI, die als Mouse/MotionListener der JTabbedPane registriert wird.
In der überschriebenen paint ( bei Swing Komponenten sollte man besser nach Möglichkeit die paintComponent überschreiben) der TabbedPane wird an einer Instanz dieser Klasse ebenfalls eine paint(Graphics) aufgerufen.

Die andere Sache ist die mit dem GUI Objekt. Wenn ich es richtig verstanden habe, ist (soll) die ClosableTabbedPane im GUI Objekt verbaut (werden). Warum besitzt die TabbedPane dann ein eigenes GUI Objekt? Wenn überhaupt notwendig, dann sollte die TabbedPane vermutlich höchstens eine Referenz auf das bestehende GUI Objekt besitzen?
 
oh man 🙁 ich habs jetzt auch mit den normalen JTabbedPane versucht 🙁 nix...

iwo vergesse ich was aber ich weiß nicht wo...


Java:
public class CreateFile extends JPanel implements ActionListener
{
 public CreateFile()
    {
        initComponents();  
        buildLayout();
        
    }

    public void initComponents() 
    {   
       //Panels 
        tabbedPane = new JTabbedPane();    
        editPanel = new EditPanel();
   }


public void buildHolePanel(){
              
      
        /*   gesamt */ 
        scrollPane.setViewportView(editPanel);
        tabbedPane.addTab("neu    ", scrollPane);
       
        GroupLayout layout = new GroupLayout(this);
        this.setLayout(layout);
        this.setBackground(darkGray);
        layout.setHorizontalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
              
                .addComponent(tabbedPane, GroupLayout.DEFAULT_SIZE,0, Short.MAX_VALUE)
                .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
                    .addComponent(websitePanel, GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(layoutPanel, GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(fixFormsPanel, GroupLayout.DEFAULT_SIZE, 0, Short.MAX_VALUE)
                    .addComponent(individualFormsPanel, GroupLayout.DEFAULT_SIZE,0, Short.MAX_VALUE)
                    .addComponent(orangeFormsPanel, GroupLayout.DEFAULT_SIZE,0, Short.MAX_VALUE))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(20 , 20, 20)
                .addComponent(websitePanel)
                .addGap(18, 18, 18)
                .addComponent(layoutPanel)
                .addGap(18, 18, 18)
                .addComponent(fixFormsPanel)
                .addGap(18, 18, 18)
                .addComponent(individualFormsPanel)
                .addGap(18, 18, 18)
                .addComponent(orangeFormsPanel)
                .addContainerGap())
                
            .addComponent(tabbedPane)            
        );  
      
    public void buildLayout(){
        buildWebsitePanel();
        buildLayoutPanel();
        buildfixFormsPanel();
        buildIndividualFormsPanel();
        buildOrangeFormsPanel();
        buildEditPanel(); 
        buildHolePanel();
    }

Java:
public class GUI extends JFrame implements ActionListener{
 public GUI() {

        initComponents();   

        setTitle("Layout Tool");
        setSize(1050,980);
       
        setLocationRelativeTo(null);

        WindowListener exitListener = new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                closeProgramm();
            }
        };
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        addWindowListener(exitListener);
       
    }

public void initComponents() {
         startPanel = new JPanel(){
                public void paint (Graphics g){
                    super.paint(g);

                    g.fillRect(0, 0, startPanel.getWidth() , startPanel.getHeight());
                    g.drawImage(img,startPanel.getWidth()/2-200,startPanel.getHeight()/2-100,null);
           
                }
        };   

        menubar = new JMenuBar();
        menuFile = new JMenu();
        menuAds = new JMenu();
             
        neu = new JMenuItem();
...
}

 public void actionPerformed(ActionEvent object) {
      
        //Neu
        if (object.getSource() == neu){    
        
        CreateFile create = new CreateFile();   
        create.deleteTF();

        saveUnder.setEnabled(true);
        setContentPane(create);    
        setVisible(true);
           
        }
 
Auch hier wieder das "Phänomen" der Neuerstellung von Objekten.

Warum wird bei jedem Klick auf den MenuItem "neu" eine neues Objekt "CreateFile" und somit ein neues JTabbedPane erzeugt?

Es sieht so aus, als weißt Du nicht wie Du Referenzen auf bestehende Objekte übergeben sollt und erstellst, damit der Code überhaupt kompiliert einfach neue Objekte.
 
ich weiß nur dass ich die sonst static machen muss .. abe rich wollt eeig nicht
Static wäre ja auch der falsche Weg. Java arbeitet mit Objekten und wenn man den Zugriff auf bestimmte Objekte tatsächlich in anderen Klassen benötigt, muss man eben eine Referenz der Objekte an entsprechender Stelle übergeben.
Wenn Du eine Methode von Objekt A in einem Objekt B aufrufen willst benötigt B eine Referenz auf A.

Java:
class B {
    private A a;

    public B(A a) {
         this.a = a;
    }

    public void letASayHello() {
         a.sayHello();      
    }
}

class A {
    public void sayHello() {
        System.out.println("Hello");
    }
}

public static void main(String[] s) {
    A a = new A();
    B b = new B(a);
    b.letASayHello();
}
 

Neue Themen


Zurück
Oben