Swing Default-Eigenschaft bei JButton

jf

Bekanntes Mitglied
Hallo, und schon hat man eine Sache gelöst, gibt es schon beim nächsten wieder Probleme... ;(

Ich möchte einem JButton die Default-Eigenschaft verpassen, damit der Nutzer im Textfeld einfach auf Enter hauen kann und damit die Eingabe trotzdem bestätigt wird.

Dazu habe ich folgendes Bespiel gefunden:

Java:
    jb.setDefaultCapable(true);
    getContentPane().add(jb, BorderLayout.EAST);
    getRootPane().setDefaultButton(jb);

Bei mir scheint aber getRootPane() null zu sein, was sich nicht gerade positiv auf den Programmablauf auswirkt.
Was ist diese RootPane genau?
Hat das etwas mit getContentPane().add() zu tun?
Gibt es nur eine RootPane pro Fenster? - Ich müsste nämlich auf mehreren Tabs eine Default-Schaltfläche platzieren, was in diesem Fall Probleme bereiten könnte.

PS:
Einen Listener für das Textfeld sehe ich nur als Notlösung, da die Default-Eigenschauft nämlich auch Auswirkung auf die visuelle Darstellung der Schaltfläche hat.
 
Zuletzt bearbeitet von einem Moderator:

bERt0r

Top Contributor
Bei sowas hilft es immer erstmal ein KSKB zu erstellen, mit dem Ziel, genau dein Problem zu reproduzieren. Wenn man die Sache nämlich nur mehr auf die Komponenten herunterbricht, die unbedingt benötigt werden, kommt man sehr viel eher auf die Ursache des Problems. Ich hab dir einen kleinen Beispielcode zusammengehackt:
Java:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class DefaultButton extends JFrame
{
	
	private JPanel contentPane;
	private JTextField textField1;
	private JRadioButton radio1;
	private JButton button1;
	private JPanel panel_1;
	private JTextField textField2;
	private JButton button2;
	private JRadioButton radio2;
	private JLabel lblTextfield;
	private JLabel lblTextfield_1;
	private JTextField txtClickToLose;
	
	/**
	 * Launch the application.
	 */
	public static void main(String[] args)
	{
		EventQueue.invokeLater(new Runnable()
			{
				public void run()
				{
					try
					{
						DefaultButton frame = new DefaultButton();
						frame.setVisible(true);
					} catch (Exception e)
					{
						e.printStackTrace();
					}
				}
			});
	}
	
	/**
	 * Create the frame.
	 */
	public DefaultButton()
	{
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);
		
		JPanel panel = new JPanel();
		FlowLayout flowLayout = (FlowLayout) panel.getLayout();
		contentPane.add(panel, BorderLayout.NORTH);
		
		ActionListener halloWelt = new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					JComponent source = (JComponent) e.getSource();
					JOptionPane.showMessageDialog(DefaultButton.this, "Hallo Welt sagt " + source.getName());
				}
			};
		
		textField1 = new JTextField();
		textField1.setName("TextField 1");
		textField1.addActionListener(halloWelt);
		
		lblTextfield = new JLabel("TextField1");
		panel.add(lblTextfield);
		panel.add(textField1);
		textField1.setColumns(10);
		
		button1 = new JButton("Button 1");
		button1.setName("Button 1");
		button1.addActionListener(halloWelt);
		panel.add(button1);
		
		ButtonGroup rGroup = new ButtonGroup();
		
		radio1 = new JRadioButton("is DefaultButton");
		radio1.addActionListener(new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					if (radio1.isSelected())
					{
						getRootPane().setDefaultButton(button1);
					}
				}
			});
		rGroup.add(radio1);
		panel.add(radio1);
		
		panel_1 = new JPanel();
		contentPane.add(panel_1, BorderLayout.SOUTH);
		
		textField2 = new JTextField();
		textField2.setName("TextField 2");
		textField2.addActionListener(halloWelt);
		
		lblTextfield_1 = new JLabel("TextField2");
		panel_1.add(lblTextfield_1);
		textField2.setColumns(10);
		panel_1.add(textField2);
		
		button2 = new JButton("Button 2");
		button2.setName("Button 2");
		button2.addActionListener(halloWelt);
		panel_1.add(button2);
		
		radio2 = new JRadioButton("is DefaultButton");
		radio2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) 
			{
				if(radio2.isSelected())
				{
					getRootPane().setDefaultButton(button2);
				}
			}
		});
		rGroup.add(radio2);
		panel_1.add(radio2);
		
		txtClickToLose = new JTextField();
		txtClickToLose.setText("Click to lose Focus");
		txtClickToLose.setEditable(false);
		contentPane.add(txtClickToLose, BorderLayout.CENTER);
		txtClickToLose.setColumns(10);
	}
	
}
 

jf

Bekanntes Mitglied
Vielen Dank für deine Mühe. Das Prinzip ist mir aber schon klar - nur liefert bei mir getRootPane() leider immer nur null - und ich weiß nicht warum... ???:L
Entschuldige bitte auch die späte Antwort - ich kam erst jetzt dazu, ein kleines Beispiel zurecht zu machen. - Ich habe veruscht, alles unnötige raus zu hauen:

Java:
import javax.swing.*;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;


@SuppressWarnings("serial")
public class MyExample extends JFrame {
    
    // constructor
    public MyExample() {
    	JTabbedPane tabsPane = new JTabbedPane();
		new Tab(tabsPane, null);
		
		this.setTitle("Beispiel-App");
		this.getContentPane().add(tabsPane);
        this.setSize(500, 500);
        this.setVisible(true);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    // main routine
    public static void main(String[] arg) throws IOException {
		try {
			UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
		}
		catch (ClassNotFoundException e) { e.printStackTrace(); }
		catch (InstantiationException e) { e.printStackTrace(); }
		catch (IllegalAccessException e) { e.printStackTrace(); }
		catch (UnsupportedLookAndFeelException e) { e.printStackTrace(); }
		
		new MyExample();		
    }
}

@SuppressWarnings("serial")
class Tab extends JPanel {
	
	private JTabbedPane m_tabCtrl    = null;
	private JPanel m_searchPane      = null;
	private JTextField m_searchField = null;
	private JButton m_enterButton    = null;
	private JList m_listCtrl         = null;
	
	private ActionListener actionListener = null;

	private enum Mode {
		ListMode,
		ConfigMode
	}
	
	private final String NEW_TAB_TITLE = "+ "; 

	
	public Tab(final JTabbedPane tabCtrl, Tab leftNeighbor) {
		m_tabCtrl = tabCtrl;
		m_listCtrl = new JList();
		m_searchPane = getSearchPane();
	
		this.setLayout(new BorderLayout());

		if(leftNeighbor == null) {					// if this is the first tab
			tabCtrl.addTab("Alle Einträge", this);
			tabCtrl.addTab(NEW_TAB_TITLE, new Tab(tabCtrl, this));
			switchMode(Mode.ListMode);
		} else {
			m_searchField.setText("Enter search string here.");
			switchMode(Mode.ConfigMode);
		}
	}

	private JPanel getSearchPane() {
		if(m_searchPane == null) {
			m_searchField  = new JTextField();
			m_enterButton  = new JButton("Knopf");
			m_enterButton.addActionListener(getActionListener());
			m_enterButton.setDefaultCapable(true);
			
			/* -----> Hier bekomme ich leider die Nullpointer-Exception! <----- */ 

			//m_tabCtrl.getRootPane().setDefaultButton(m_enterButton);
			//this.getRootPane().setDefaultButton(m_enterButton);
			System.out.println(getRootPane());
			
			/* ---------------------------------------------------------------- */
			
			m_searchField.setPreferredSize(  new Dimension(200, 19) );
			m_enterButton.setPreferredSize(  new Dimension(100, 22) );
			
			m_searchPane = new JPanel();
			m_searchPane.setLayout( new FlowLayout() );
			m_searchPane.add(m_searchField);
			m_searchPane.add(m_enterButton);
		}
		return m_searchPane;
	}
	
	private ActionListener getActionListener() {
		final Tab This = this;
		
		if(actionListener == null) {
			actionListener = new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent ev) {
					String searchString = m_searchField.getText();
					m_tabCtrl.setTitleAt(m_tabCtrl.getSelectedIndex(), "Einträge mit " + searchString);
					switchMode(Mode.ListMode);
					m_tabCtrl.add(NEW_TAB_TITLE, new Tab(m_tabCtrl, This));
				}
				
			};
		}
		return actionListener;
	}

	private void switchMode(Mode mode) {
		if(mode == Mode.ListMode) {
			this.add(m_listCtrl, BorderLayout.CENTER);
			m_listCtrl.setVisible(true);
			m_searchPane.setVisible(false);
		} else {
			this.add(m_searchPane, BorderLayout.CENTER);
			m_searchPane.setVisible(true);
			m_listCtrl.setVisible(false);
		}
	}

}
 

GUI-Programmer

Top Contributor
Du solltest getRootPane() auch nicht auf ein JPanel aufrufen, sondern von einer Klasse die von JWindow erbt. Warum weiß ich jetzt grad nicht mehr, kannst ja mal Google oder Forensuche fragen, oder warten bis dir hier einer den Grund liefert.
 

jf

Bekanntes Mitglied
Ok, alles klar. - Aber warum besitzen solche Klassen dann überhaupt solch eine Methode?

=> Meine Tab-Klasse weiß von dem Fenster, in welchem es sich befindet nichts. Komme ich trotzdem irgendwie an diese Information in der Art
Code:
m_tabCtrl.getParent().getContentPane()
heran?

Nebenfrage:
Welche Vorteile bietet überhaupt der Aufruf des Fensters über InvokeLater?
Java:
    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    try
                    {
                        DefaultButton frame = new DefaultButton();
                        frame.setVisible(true);
                    } catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            });
    }
 

jf

Bekanntes Mitglied
1. Indem du die Instanz des JFrames einfach im Konstruktor mit übergibts.
Klar, das finde ich aber unschön, weil es die Verwendung der Klasse verkompliziert.
Bei anderen Sprachen hat man oftmals die Möglichkeit, über die Komponente das Fenster zu ermitteln, in welchem sich selbige befindet. - Ist das bei Java wirklich nicht möglich?

2. Google einfach mal nach Event Dispatch Thread (EDT).
Ok, danke.
 

GUI-Programmer

Top Contributor
Die Methode getRootPane() kannst du sehr wohl auf ein JPanel oder auf sonst einer Klasse aufrufen, die von JComponent erbt. Sie liefert sogar die JRootPane des JFrames (also ist ein
Code:
panel.getParent().getParent()...
unnötig), allerding nur dann, wenn die Komponente selbst bereits dem JFrame (auch durch großer Verschachtelung wie JFrame --> JPanel --> JPanel, etc.) angehört, also "geaddet" wurde.

Das bedeutet für dich erst die JTabbedPane der ContentPane des JFrames adden, dann deine Tab-Klasse erzeugen oder der Tab-Klasse eine Methode geben, die deinen JButton der JRootPane als DefaultButton zuweist, welche du aufrufst, nachdem deine JTabbedPane dem JFrame hinzugefügt wurde.

Somit war meine Aussage falsch:
[WR]
Du solltest getRootPane() auch nicht auf ein JPanel aufrufen, sondern von einer Klasse die von JWindow erbt.
[/WR]
 
Zuletzt bearbeitet:

jf

Bekanntes Mitglied
allerding nur dann, wenn die Komponente selbst bereits dem JFrame (auch durch großer Verschachtelung wie JFrame --> JPanel --> JPanel, etc.) angehört, also "geaddet" wurde.

Das bedeutet für dich erst die JTabbedPane der ContentPane des JFrames adden, dann deine Tab-Klasse erzeugen oder der Tab-Klasse eine Methode geben, die deinen JButton der JRootPane als DefaultButton zuweist, welche du aufrufst, nachdem deine JTabbedPane dem JFrame hinzugefügt wurde.
Ok, das werde ich mal versuchen. Vielen Dank.

Ich habe ja mehrere Tabs, welche solch einen Default-Knopf bräuchten. - Hier werde ich wohl dynamisch bei jedem Tabwechsel anpassen müssen. Oder?


Dann hätte ich noch eine kurze Frage zu folgendem Code:
Java:
    private void switchMode(Mode mode) {
        if(mode == Mode.ListMode) {
            this.add(m_listCtrl, BorderLayout.CENTER);
            m_listCtrl.setVisible(true);
            m_searchPane.setVisible(false);
        } else {
            this.add(m_searchPane, BorderLayout.CENTER);
            m_searchPane.setVisible(true);
            m_listCtrl.setVisible(false);
        }
    }
Ist diese Lösung zum Wechsel zweier Panels akzeptabel? - Oder gibt es da vlt. einen elganteren Weg?
 

GUI-Programmer

Top Contributor
Ist diese Lösung zum Wechsel zweier Panels akzeptabel? - Oder gibt es da vlt. einen elganteren Weg?

Ja, und zwar indem du das CardLayout verwendest.

Zum anderen kann ich dir nur sagen, dass da auch die Möglichkeit wäre den umgebenden Komponenten einen KeyListener bzw. ActionListener zu geben, der dann einen Klick.auf den JButton ausführen lässt. Alternativ dazu könnte man auch den ganzen JButtons, die als DefaultButtons dienen sollen einen ComponentListener veepassen. Dann wenn der jeweilige JButton erscheint, also componentShown aufgerufen wird einfach den JButton zum DefaultButton machen.

Zur 1. Variante, die ich persönlich besser finde, kann ich dir später ja noch ein bisschen Code geben, wenn denn benötigt wird.
 

jf

Bekanntes Mitglied
Die Methode getRootPane() kannst du sehr wohl auf ein JPanel oder auf sonst einer Klasse aufrufen, die von JComponent erbt. Sie liefert sogar die JRootPane des JFrames (also ist ein
Code:
panel.getParent().getParent()...
unnötig), allerding nur dann, wenn die Komponente selbst bereits dem JFrame (auch durch großer Verschachtelung wie JFrame --> JPanel --> JPanel, etc.) angehört, also "geaddet" wurde.

Das bedeutet für dich erst die JTabbedPane der ContentPane des JFrames adden, dann deine Tab-Klasse erzeugen
Dies habe ich gerade ausprobiert, dennoch liefert getRootPane() stets null:
Java:
		JTabbedPane tabsPane = new JTabbedPane();
		this.getContentPane().add(tabsPane);
		new Tab(tabsPane, null);
 

GUI-Programmer

Top Contributor
Hab mir deinen Code gearde nochmal angeschaut und mir ist auch sofort klar geworden warum. Und zwar addest du jetzt zuerst die JTabbedPane dem JFrame, rufst aber in deiner Tab-Klasse, die von JPanel erbt, getRootPane schon wieder falsch/zu bald auf, da du die Tab Klasse erst nach diesem Aufruf mit
Code:
tabCtrl.addTab("Alle Einträge", this);
der JTabbedPane hinzufügst, umd somit die "Kette" hin zum JFrame wieder steht.

Also entweder getRootPane auf m_tabCtrl bzw. tabCtrl aufrufen, da diese ja bereits dem JFrame geaddet wurde, oder getRootPane in Tab erst aufrufen, wenn bereits zugehörig zu der JTabbedPane.
 
Zuletzt bearbeitet:

jf

Bekanntes Mitglied
Hab mir deinen Code gearde nochmal angeschaut und mir ist auch sofort klar geworden warum. Und zwar addest du jetzt zuerst die JTabbedPane dem JFrame, rufst aber in deiner Tab-Klasse, die von JPanel erbt, getRootPane schon wieder falsch/zu bald auf, da du die Tab Klasse erst nach diesem Aufruf mit
Code:
tabCtrl.addTab("Alle Einträge", this);
der JTabbedPane hinzufügst, umd somit die "Kette" hin zum JFrame wieder steht.

Also entweder getRootPane auf m_tabCtrl bzw. tabCtrl aufrufen, da diese ja bereits dem JFrame geaddet wurde, oder getRootPane in Tab erst aufrufen, wenn bereits zugehörig zu der JTabbedPane.
Du hast natürlich Recht!
Ich habe es irgenwie genau wechselseitig gemacht: im Beispiel habe ich an der einen Stelle vergessen - in meinem richtigen Projekt an der anderen... :bahnhof:

Das habe ich nun korrigiert. getRootPane() ist nun nicht mehr null.
Aber ich habe immer noch Probleme mit folgendem:
Alternativ dazu könnte man auch den ganzen JButtons, die als DefaultButtons dienen sollen einen ComponentListener veepassen. Dann wenn der jeweilige JButton erscheint, also componentShown aufgerufen wird einfach den JButton zum DefaultButton machen.

Die Methode wird nie ausgeführt (keine Ausgabe "Shown") - hier ist meine Implementierung:
Java:
			m_enterButton.addComponentListener(new ComponentListener() {
				@Override public void componentResized(ComponentEvent ev) {}
				@Override public void componentMoved(ComponentEvent ev) {}
				@Override public void componentHidden(ComponentEvent ev) {}
				@Override
				public void componentShown(ComponentEvent ev) {
					System.out.println("Shown");
					JButton source = (JButton)ev.getSource();
					source.getRootPane().setDefaultButton(source);
				}
			});
 

bERt0r

Top Contributor
Ich wollte mit meinem Beispiel oben eigentlich demonstrieren, dass man auch auf ein TextField einen actionlistener adden kann. Das heisst der wird dann ausgeführt, wenn man im TextField Enter drückt, egal was der DefaultButton ist.
 

jf

Bekanntes Mitglied
Ich wollte mit meinem Beispiel oben eigentlich demonstrieren, dass man auch auf ein TextField einen actionlistener adden kann. Das heisst der wird dann ausgeführt, wenn man im TextField Enter drückt, egal was der DefaultButton ist.
Ja, das halte ich aber nur für eine Notlösung, da es der Default-Eigenschaft nicht äquivalent ist.
(z. B. nicht das Aussehen des Default-Buttons ändert)

Die ComponentListener-Lösung wäre ja schon sehr gut - nur feuert das Shown-Ereignis nicht. Woran könnte das denn liegen?
 

bERt0r

Top Contributor
Die ComponentListener "Lösung" ist Murks und sonst nichts. Warum übergibst du deiner Tab-Klasse nicht einfach das RootPane im Konstruktor?
 

jf

Bekanntes Mitglied
Die ComponentListener "Lösung" ist Murks und sonst nichts. Warum übergibst du deiner Tab-Klasse nicht einfach das RootPane im Konstruktor?
Das RootPane-Problem ist ja mittlerweile gelöst. Den ComponentListener möchte ich jetzt dazu verwenden, den verschiedenen Schaltflächen (jeweils auf einem Tab einer) abwechselned die Default-Eigenschaft zu geben - es kann ja immer nur einen solchen Knopf geben...
 

GUI-Programmer

Top Contributor
Hab mir deinen Code gearde nochmal angeschaut und mir ist auch sofort klar geworden warum. Und zwar addest du jetzt zuerst die JTabbedPane dem JFrame, rufst aber in deiner Tab-Klasse, die von JPanel erbt, getRootPane schon wieder falsch/zu bald auf, da du die Tab Klasse erst nach diesem Aufruf mit tabCtrl.addTab("Alle Einträge", this); der JTabbedPane hinzufügst, umd somit die "Kette" hin zum JFrame wieder steht.

Also entweder getRootPane auf m_tabCtrl bzw. tabCtrl aufrufen, da diese ja bereits dem JFrame geaddet wurde, oder getRootPane in Tab erst aufrufen, wenn bereits zugehörig zu der JTabbedPane.
Du hast natürlich Recht!
Ich habe es irgenwie genau wechselseitig gemacht: im Beispiel habe ich an der einen Stelle vergessen - in meinem richtigen Projekt an der anderen... :bahnhof:

Das habe ich nun korrigiert. getRootPane() ist nun nicht mehr null.

Ja, gut. Hab meinen Vorschlag (nicht den mit den ComponentListener) auch mal umgesetzt:
Java:
import javax.swing.*;
 
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
 
 
@SuppressWarnings("serial")
public class TestExample extends JFrame {
    
    // constructor
    public TestExample() {
        JTabbedPane tabsPane = new JTabbedPane();
        
        this.setTitle("Beispiel-App");
        this.getContentPane().add(tabsPane);
		
		// **************************************************************
		// Hier der entscheidente Teil:
		// Der neue Tab wird erst erzeugt, wenn die JTabbedPane bereits
		// dem JFrame hinzugefügt wurde.
		new Tab(tabsPane, null);
		// **************************************************************
		
        this.setSize(500, 500);
        this.setVisible(true);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
    
    // main routine
    public static void main(String[] arg) throws IOException {
        try {
            UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
        }
        catch (ClassNotFoundException e) { e.printStackTrace(); }
        catch (InstantiationException e) { e.printStackTrace(); }
        catch (IllegalAccessException e) { e.printStackTrace(); }
        catch (UnsupportedLookAndFeelException e) { e.printStackTrace(); }
        
        new TestExample();        
    }
}
 
@SuppressWarnings("serial")
class Tab extends JPanel {
    
    private JTabbedPane m_tabCtrl    = null;
    private JPanel m_searchPane      = null;
    private JTextField m_searchField = null;
    private JButton m_enterButton    = null;
    private JList m_listCtrl         = null;
    
    private ActionListener actionListener = null;
 
    private enum Mode {
        ListMode,
        ConfigMode
    }
    
    private final String NEW_TAB_TITLE = "+ "; 
 
    
    public Tab(final JTabbedPane tabCtrl, Tab leftNeighbor) {
        m_tabCtrl = tabCtrl;
        m_listCtrl = new JList();
        m_searchPane = getSearchPane();
    
        this.setLayout(new BorderLayout());
 
        if(leftNeighbor == null) {                  // if this is the first tab
            tabCtrl.addTab("Alle Einträge", this);
            tabCtrl.addTab(NEW_TAB_TITLE, new Tab(tabCtrl, this));
            switchMode(Mode.ListMode);
        } else {
            m_searchField.setText("Enter search string here.");
            switchMode(Mode.ConfigMode);
			// *****************************************************************
			// Hier der Beweis, da die JTabbedPane bereits dem JFrame angehört,
			// liefert getRootPane() nicht null.
			System.out.println(tabCtrl.getRootPane());
			// Somit wäre folgendes hier möglich:
			tabCtrl.getRootPane().setDefaultButton(m_enterButton);
			// Wodurch dein Ziel in sofern erreicht wird, da nun immer der JButton
			// des neu erstellen Tabs der DefaultButton ist.
			// *****************************************************************
        }
    }
 
    private JPanel getSearchPane() {
        if(m_searchPane == null) {
            m_searchField  = new JTextField();
            m_enterButton  = new JButton("Knopf");
            m_enterButton.addActionListener(getActionListener());
            m_enterButton.setDefaultCapable(true);
            
            m_searchField.setPreferredSize(  new Dimension(200, 19) );
            m_enterButton.setPreferredSize(  new Dimension(100, 22) );
            
            m_searchPane = new JPanel();
            m_searchPane.setLayout( new FlowLayout() );
            m_searchPane.add(m_searchField);
            m_searchPane.add(m_enterButton);
        }
        return m_searchPane;
    }
    
    private ActionListener getActionListener() {
        final Tab This = this;
        
        if(actionListener == null) {
            actionListener = new ActionListener() {
 
                @Override
                public void actionPerformed(ActionEvent ev) {
                    String searchString = m_searchField.getText();
                    m_tabCtrl.setTitleAt(m_tabCtrl.getSelectedIndex(), "Einträge mit " + searchString);
                    switchMode(Mode.ListMode);
                    m_tabCtrl.add(NEW_TAB_TITLE, new Tab(m_tabCtrl, This));
                }
                
            };
        }
        return actionListener;
    }
 
    private void switchMode(Mode mode) {
        if(mode == Mode.ListMode) {
            this.add(m_listCtrl, BorderLayout.CENTER);
            m_listCtrl.setVisible(true);
            m_searchPane.setVisible(false);
        } else {
            this.add(m_searchPane, BorderLayout.CENTER);
            m_searchPane.setVisible(true);
            m_listCtrl.setVisible(false);
        }
    }
 
}

Funktioniert soweit ganz gut, nur dass manchal einfach leere "+ - Tabs" darin vorkommen. D.h. man müsst immer auf den letzten Tab springen.

...es kann ja immer nur einen solchen Knopf geben...

Würde ja so funktionieren.
 
Zuletzt bearbeitet:

bERt0r

Top Contributor
Für sowas gibts den ChangeListener:
Java:
import java.awt.BorderLayout;


public class TabPaneChange extends JFrame
{
	
	private JPanel contentPane;
	private JTabbedPane tabbedPane;
	
	/**
	 * Launch the application.
	 */
	public static void main(String[] args)
	{
		EventQueue.invokeLater(new Runnable()
			{
				public void run()
				{
					try
					{
						TabPaneChange frame = new TabPaneChange();
						frame.setVisible(true);
					} catch (Exception e)
					{
						e.printStackTrace();
					}
				}
			});
	}
	
	/**
	 * Create the frame.
	 */
	public TabPaneChange()
	{
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		contentPane.setLayout(new BorderLayout(0, 0));
		setContentPane(contentPane);
		
		tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		tabbedPane.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) 
			{
				Tab showingTab=(Tab)tabbedPane.getSelectedComponent();
				if(showingTab!=null)
				{
					TabPaneChange.this.getRootPane().setDefaultButton(showingTab.getButton());
				}
			}
		});
		contentPane.add(tabbedPane, BorderLayout.CENTER);
		
		JPanel panel = new JPanel();
		tabbedPane.addTab("Tab 1",null, new Tab("Button von Tab 1"), null);
		tabbedPane.addTab("Tab 2",null, new Tab("Button von Tab 2"), null);
		tabbedPane.addTab("Tab 3",null, new Tab("Button von Tab 3"), null);
	}
	
	class Tab extends JPanel
	{
		JButton button;
		public Tab(String buttonName)
		{
			button=new JButton(buttonName);
			button.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent e)
				{
					JButton button=(JButton) e.getSource();
					System.out.println(button.getText()+" wurde geklickt.");
				}
			});
			this.add(button);
		}
		
		public JButton getButton()
		{
			return button;
		}
	}
	
}
 

jf

Bekanntes Mitglied
Erst einmal vielen Dank ihr beiden: das Default-Button-Problem ist nun auch gelöst! :applaus:

Die Lösung von GUI-Programmer hat bereits gereicht, da der Knopf stets nur auf dem letzten Tab zu sehen ist - d. h. beim Zurückspringen auf einen linken Tab muss keine Default-Eigenschaft geändert werden.

Dennoch habe ich jetzt einen ChangeListener implementiert, da beim Aktivieren des letzen Tabs der Fokus auf das Text-Feld fallen sollte. Allerding funktioniert bei mir der Aufruf der Methode .grabFocus() nicht - bei dem Beispiel von GUI-Programmer funktioniert es aber sogar ohne jegelichen Extra-Code, sobald der Default-Knopf geklickt wird!
Das mit dem Fokus-Management scheint bei Swing etwas komplizierter zu sein...
Erschwerend kommt hinzu, dass das ChangeListener immer zwei Events erzeugt: wahrscheinlich Deselektierung des alten und dann Selektierung des neuen Tabs. - Wie finde ich heraus, um welches Ereignis es sich nun genau handelt? Die Doku zum ChangeEvent schweigt sich dazu leider aus...
 

GUI-Programmer

Top Contributor
Das Problem haben bERt0r und ich jetzt zwar schon erfolgreich gelöst, aber hierzu
Allerding funktioniert bei mir der Aufruf der Methode .grabFocus() nicht

kann ich nur sagen, dass man glaub ich eher requestFocus() oder requestFocusInWindow() aufrufen sollte. Dann klappt auch das.
 

jf

Bekanntes Mitglied
Das Problem haben bERt0r und ich jetzt zwar schon erfolgreich gelöst
Ja, dafür gab es ja dass Applaus-Smiley. :toll:

aber hierzu kann ich nur sagen, dass man glaub ich eher requestFocus() oder requestFocusInWindow() aufrufen sollte. Dann klappt auch das.
Hierzu muss ich nun sagen, dass ich so ****isch war, anstatt grabFocus() auf das Textfeld, auf die Schaltfläche anzuwenden (wahrscheinlich weil ich aufgrund des Default-Problems zu viel mit dieser Komponente gemacht habe :D)... - das konnte damit natürlich nicht funktionieren!

Richtig gemacht, funktioniert auch grabFocus() - aber warum gibt es überhaupt so viele ähnliche Methoden?
Java:
		this.m_searchField.grabFocus();
		this.m_searchField.requestFocusInWindow();
		this.m_searchField.requestFocus();
		this.m_searchField.requestFocus(temporary);
		this.m_searchField.requestDefaultFocus();
 

bERt0r

Top Contributor
Wenn du nicht weisst was eine Methode macht, ist es am besten, du schaust dir die JavaDoc dazu an. Google einfach nach der Klasse. GrabFocus solltest du z.B gar nicht verwenden, lieber requestFoucs. Dass es so viele derartige Methoden gibt liegt auch daran, dass manche veraltet sind und nur aufgrund der Abwärtskompatibilität noch existieren.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
C Default table model aktualisieren AWT, Swing, JavaFX & SWT 7
Hatsi09 JCombobox default wert AWT, Swing, JavaFX & SWT 6
T Default Table wird nicht angezeigt AWT, Swing, JavaFX & SWT 15
M Default-WindowListener JFrame entfernen (Stichwort: iconified) AWT, Swing, JavaFX & SWT 4
M JavaFX Scrollpane: Style von Contentpanel default AWT, Swing, JavaFX & SWT 1
Tom299 JavaFX Default-Cursor läßt sich nicht immer "aktivieren" AWT, Swing, JavaFX & SWT 3
R Ändern Default-Verhalten von JScrollpane in einer JScrollpane AWT, Swing, JavaFX & SWT 1
B Swing JTextPane - Einfärbungen auf "default" AWT, Swing, JavaFX & SWT 2
H default cell renderer AWT, Swing, JavaFX & SWT 3
C Swing Default Werte für JFormattedTextField und Eingaben zurücksetzen AWT, Swing, JavaFX & SWT 5
M SWT DateTime per default null Wert ? AWT, Swing, JavaFX & SWT 3
S JTextField Default Text AWT, Swing, JavaFX & SWT 5
K Swing Wie ändere ich die default action für Drag&Drop AWT, Swing, JavaFX & SWT 6
G Wie komm ich z.B. an das Default WarningMessageIcon ran? AWT, Swing, JavaFX & SWT 2
R TreeViewer in SWT: Default Selection eines Items AWT, Swing, JavaFX & SWT 3
hdi non-default close operation bei JDialog AWT, Swing, JavaFX & SWT 2
I Default Button AWT, Swing, JavaFX & SWT 5
G setLookAndFeel to default LookAndFeel? AWT, Swing, JavaFX & SWT 4
I "default"-Style im DefaultStyledDocument AWT, Swing, JavaFX & SWT 2
G default Layout für JPanel AWT, Swing, JavaFX & SWT 2
T Ändern des Default-Aussehens einer JComboBox AWT, Swing, JavaFX & SWT 3
D FileFilter Default Eintrag AWT, Swing, JavaFX & SWT 4
S Default Button in Dialogs(Ok und Cancel) AWT, Swing, JavaFX & SWT 4
H default format settings AWT, Swing, JavaFX & SWT 11
A (Default)TreeModel und wie die Daten hinein bekommen AWT, Swing, JavaFX & SWT 5
P Default Link in Swing, --> öffne Browser -> Browse URL AWT, Swing, JavaFX & SWT 8
N JavaFX Stranges Problem mit der Autoscroll-Eigenschaft von Textareas AWT, Swing, JavaFX & SWT 0
Daniel_L Mac-Eigenschaft apple.awt.documentModalSheet? AWT, Swing, JavaFX & SWT 2
K nervende eigenschaft von eclipse AWT, Swing, JavaFX & SWT 3
G JButton mit importFiles-Funktion auf JDrawPane AWT, Swing, JavaFX & SWT 5
B JButton Search AWT, Swing, JavaFX & SWT 8
B Swing JButton mit KeyListener AWT, Swing, JavaFX & SWT 3
L JButton durch Mausklick auslösen und Enter-Taste AWT, Swing, JavaFX & SWT 2
N Erlennen ob JButton gedrückt ist AWT, Swing, JavaFX & SWT 6
D JButton Form verändern AWT, Swing, JavaFX & SWT 4
R Grafik per JButton laden und austauschen lassen AWT, Swing, JavaFX & SWT 14
SvenPittelkow Programm soll auf JButton warten bis der geklickt wurde AWT, Swing, JavaFX & SWT 1
Badebay Problem mit JButton AWT, Swing, JavaFX & SWT 2
Z Swing Drag and Drop mit einem JButton AWT, Swing, JavaFX & SWT 1
Z Swing Kann man auf JButton zeichenen AWT, Swing, JavaFX & SWT 3
J JButton Icon hinzufügen AWT, Swing, JavaFX & SWT 5
U Swing JButton mit Icon AWT, Swing, JavaFX & SWT 7
ms_cikar Jbutton erzeugt neue Buttons AWT, Swing, JavaFX & SWT 2
Drachenbauer Swing Wie ändere ich die Farbe der Konturen von jButton und jCombobox? AWT, Swing, JavaFX & SWT 18
Drachenbauer Swing Wie ändere ich die helle geklickt-Farbe von einem JButton? AWT, Swing, JavaFX & SWT 4
A Swing JButton mit Pfeiltasten bewegen AWT, Swing, JavaFX & SWT 6
F Swing Scrollbare Liste von JButton AWT, Swing, JavaFX & SWT 4
Hatsi09 JButton text layout AWT, Swing, JavaFX & SWT 9
J JButton zum ändern Der Schriftart/Schriftgröße AWT, Swing, JavaFX & SWT 2
A Swing JButton aussehen AWT, Swing, JavaFX & SWT 12
J jButton soll nach klicken eine Variable um 1 erhöhen AWT, Swing, JavaFX & SWT 2
Legi Swing JButton Icon verschiebt sich AWT, Swing, JavaFX & SWT 2
T Swing Änderung des ActionListener Events nach Klick auf JButton AWT, Swing, JavaFX & SWT 2
S Swing JButton verschwindet nach Compilieren AWT, Swing, JavaFX & SWT 8
B Swing Posistion von JButton auslesen gibt immer 0 aus AWT, Swing, JavaFX & SWT 1
J Thread kennt JButton nicht. AWT, Swing, JavaFX & SWT 11
G Swing JButton ändert (unerwünscht) Größe bei Ausführung AWT, Swing, JavaFX & SWT 4
MR._FIRE_Flower Variable setzten mit JButton AWT, Swing, JavaFX & SWT 5
S Mit JButton neues Fester öffnen und das alte schließen AWT, Swing, JavaFX & SWT 3
T JButton wird beim vergrößern des Fensters erst sichtbar AWT, Swing, JavaFX & SWT 4
R Swing Verändern der Ausrichtung JButton und neu anzeigen AWT, Swing, JavaFX & SWT 2
G Swing JButton - Keine Klickanimation AWT, Swing, JavaFX & SWT 4
Joker4632 JButton nicht sichtbar, aber funktionsfähig AWT, Swing, JavaFX & SWT 8
B Swing JButton deaktivieren, wenn nicht alle JTextFields ausgefüllt sind. AWT, Swing, JavaFX & SWT 2
D JButton per Tastenkombi auswählen AWT, Swing, JavaFX & SWT 2
K JButton nicht sichtbar machen für User 2 AWT, Swing, JavaFX & SWT 4
L Swing JButton soll link öffnen AWT, Swing, JavaFX & SWT 1
K JButton auf anderer Klasse AWT, Swing, JavaFX & SWT 6
A JButton soll durch anklicken die Farbe wechseln AWT, Swing, JavaFX & SWT 8
T KeyListener funktioniert nicht wenn ich ein JButton hinzufüge AWT, Swing, JavaFX & SWT 1
R Swing ActionListener bei JButton AWT, Swing, JavaFX & SWT 9
B JButton -> Rahmen wegbekommen AWT, Swing, JavaFX & SWT 7
N JButton über benutzerdefinierte paintComponent setzen AWT, Swing, JavaFX & SWT 3
T JButton überlagern sich und werden erst beim Mausscrollen sichtbar AWT, Swing, JavaFX & SWT 2
B JButton erscheint in JFrame, obwohl er diesem nicht zugeordnet wurde! AWT, Swing, JavaFX & SWT 1
M JButton Probleme AWT, Swing, JavaFX & SWT 14
T Klasse über JButton schließen AWT, Swing, JavaFX & SWT 4
M Textfarbe JButton verändern AWT, Swing, JavaFX & SWT 2
N JButton ausblenden AWT, Swing, JavaFX & SWT 2
M Swing jButton Text verschwindet AWT, Swing, JavaFX & SWT 2
C Swing JButton wird nicht angezeigt AWT, Swing, JavaFX & SWT 2
stylegangsta JLabel durch Klick auf JButton einblenden AWT, Swing, JavaFX & SWT 16
stylegangsta Eigene Klasse für JButton aus dem JFrame abrufen AWT, Swing, JavaFX & SWT 29
stylegangsta MouseEvents aus JButton aufrufen AWT, Swing, JavaFX & SWT 3
stylegangsta JButton Transparent anzeigen AWT, Swing, JavaFX & SWT 9
stylegangsta JButton Fehelr javax.swing.ImageIcon.<init>(Unknown Source) AWT, Swing, JavaFX & SWT 24
X Swing JButton's zum JScrollPane hinzufügen geht nicht. Bitte um Hilfe. AWT, Swing, JavaFX & SWT 9
D JButton - Nur Icon anzeigen / transparenter Hintergrund AWT, Swing, JavaFX & SWT 2
S JButton-Label vergrößern AWT, Swing, JavaFX & SWT 2
J Swing Basics - JButton funktioniert nicht. AWT, Swing, JavaFX & SWT 1
L JButton mit ImageIcon/Fehlermeldung AWT, Swing, JavaFX & SWT 1
D jButton Problem, ein Rieser Button bedeckt das ganze frame AWT, Swing, JavaFX & SWT 1
L Array mit JButton, wie rausfinden auf welche JButton geklickt wurde + index des JButtons ausgeben AWT, Swing, JavaFX & SWT 4
K (GUI) JButton Farbe bei druck ändern AWT, Swing, JavaFX & SWT 3
L JButton mit Image AWT, Swing, JavaFX & SWT 5
fLooojava JButton [Focus) AWT, Swing, JavaFX & SWT 4
M JButton - Listener AWT, Swing, JavaFX & SWT 1
D jButton auf von jFrame erzeugtem jDialog AWT, Swing, JavaFX & SWT 16
L JButton flackern - Programm hängt sich auf AWT, Swing, JavaFX & SWT 3
L JButton - Größe anders als erwartet AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben