Multiple tabs in JTabbedPane using a single JPanel? - java

Is it possible to use a single JPanel for multiple tab items in JTabbedPane?
EG:
JTabbedPanel tabs=new JTabbePanel();
JPanel panel=new JPanel();
JButton but=new JButton("TEXT");
but.addActionlistener(this);
panel.add(but)
tabs.add("First",panel);
tabs.add("Second",panel);
An ActionListener is added to the JTabbedPane to notify the program of tab changes (change cur_tab to tab number)
public void actionPerformed(..)
{ System.out.println("Now in "+cur_tab); }

The same component cannot be used for several tabs
taken from here

Sounds like you need a subclass of JPanel. Just create an abstract class that handles the complex layout and have the subclasses create the necessary GUI elements that are required.
If you are just inserting a single text box, button, etc, you may not even need subclasses per tab. Just create multiple instances of the base class and add the component you need.
New panels and other GUI items are relatively cheap. Performance issues in a Swing GUI are more likely to come from event handling or firing too many events rather than how complex or how many components it has. Make things easier to maintain and understand, then worry about performance.

if you'll create class that returns JPanel then yes that's possible
but Notice:
there are long time Bug that two Tabs can't contains same component schemas, with schemas I means for example one Tab contains JPanel + JTextField + JButton, but then second JPanel must contains another Numbers or Type of JComponents
unfortunatelly (nothing special) BugsDatabase isn't accesible in this moment

I had a panel with memory-intensive components on it which I only wanted to create one instance of, but change the behaviour of it using the attractive JTabbedPane.
I did it by creating empty panels for each tab, and a third panel that contains my (single) complicated components. On the StateChange event for the JTabbedPane, I remove the third panel from whichever of the first two it was in, and add it to whichever one is newly selected.
Bit hacky, but it works fine.

You are wrong.
Just set a panel on the first tab in function initComponents() like that:
p.add("1", MainPanel);
Then use:
p.add("2", p.getTabComponentAt(0));
Using this metode you will have the same component on 2 tabs.
You can use StateChanged Event to change actions in this tabs.
For example:
JTabbedPane p = (JTabbedPane)Tabbar;
int idx = p.getSelectedIndex();
if(idx==0){
Do something...
}
if(idx==1){
Do something different...
}

The following will allow you to add the same component with different titles to a JTabbedPane:
JTabbedPane tabbedPane = new JTabbedPane()
{
boolean adding = false;
#Override
public void removeTabAt(int index)
{
if(!adding)
{
super.removeTabAt(index);
}
}
#Override
public void insertTab(String title, Icon icon, Component component, String tip, int index)
{
adding = true;
super.insertTab(title, icon, component, tip, index);
adding = false;
}
};

Related

Java: MouseListener of JPanel behind JTextAreas

I've created a component that basically is a JPanel fully covered with (non-editable) JTextAreas. I want a MouseListener to be fired everytime the JPanel area is being clicked on. I do want to add the Listener once to the JPanel instead of n times to the JTextAreas.
Is there a way to send the JTextAreas to background, so the JPanel is clicked "through" the JTextArea?
Note: With JLabels this works without anything special, the JPanels Listener is always fired, but I prefer JTextAreas, because of the linebreak.
With JLabels this works without anything special, the JPanels Listener is always fired
This is because by default a JLabel does not contain a MouseListener so the MouseEvent is passed up the parent tree until a component the does use a MouseListener is found.
In the case of a JTextArea a MouseListener is added to the text area so you can position the caret and select text etc. If you don't need all this functionality you can remove the MouseListener from each text area with code something like:
JTextArea textArea = new JTextArea(...);
MouseListener[] ml = (MouseListener[])textArea.getListeners(MouseListener.class);
for (int i = 0; i < ml.length; i++)
textArea.removeMouseListener( ml[i] );
However, since you have to do that for every text area, I would suggest it is easier to just add the MouseListener to each text area. You can share the same MouseListener with every text area.
There is a solution proposed here, but it might not fully work for your needs.
I don't know if there is a way around adding the listener n times, but if there is not, you could integrate the process cleanly in your code.
For example, with a dedicated method to add the JTextAreas:
public void addJTextArea(JTextArea tArea){
this.add(tArea, ...);
tArea.addMouseListener(this.listener);
}
Or even more transparently with an extended JTextArea:
public class ClickableTextArea extends JTextArea {
public ClickableTextArea(MouseListener listener){
super();
addMouseListener(listener);
}
}

Can you change UI property through DocumentListener in java?

I am trying to set gmailPasswordField.setVisible(true) & senderPasswordLabel.setVisible(true) if the JTextField is changed, but it's not working.
doc.addDocumentListener(
new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
int minLengthEmail = "n#gmail.com".length();
if (countDocumentChangeLength > minLengthEmail) {
gmailPasswordField.setVisible(true); // Doesn't appear to do anything
senderPasswordLabel.setVisible(true); // Nor this
}
}
});
Did you add a System.out.println(...) to see if the code is being executed? This is a basic debugging technique to see if the code is executing as you expect.
The changedUpdate(...) method is invoked when you change an attribute of the text.
I suspect you want to implement the other DocumentListener methods so you will be notified when the "text" in the Document changes. Read the section from the Swing tutorial on How to Write a DocumentListener for more information and working examples.
Don't use the method setVisible(boolean). Use CardLayout instead.
Little howto:
Move your widgets, which visibility must be switched, into a new JPanel (layout panel).
Create another JPanel with CardLayout (card panel) and place the layout panel into it.
Place an empty JPanel into the card panel.
Make sure that the appropriate card is visible (in your case - the empty card).
Make another card visible when required (in your document listener).

Delete element from GridBagLayout

how can I delete element from GridBagElement ?
http://i.stack.imgur.com/1BsDW.jpg
I want to remove the selected item by clicking on the button.
How can I send the name of the selected item as a parameter to the action button?
First, you don't delete from GridBagLayout. With swing you add Components to a Container, and you remove them from a Container.
http://docs.oracle.com/javase/6/docs/api/java/awt/Container.html#remove%28java.awt.Component%29
To select the Green Panel you can Register an ActionListener or MouseListener for this Panel.
The MouseListener delivers the MouseEvent.
The MouseEvent can get you the Source with getSource, which is the green Panel.
And that panel can be removed.
A simple example snippet:
final JPanel mainPanel = new JPanel();
JPanel greenPanel = new JPanel();
greenPanel.addActionListener(new ActionListener(){
#Override
public void ActionPerformed(ActionEvent e){
int answer = JOptionPane.showConfirmDialog(null, "Delete?");
if(answer == JOptionPane.YES_OPTION){
mainPanel.remove(e.getSource());
}
}
});
mainPanel.add(greenPanel);
You will want to establish some kind of contract between things like buttons and other controls and your view.
Things that want to modify the view should not be able to do anything you don't want them to (like change the layout for instance).
I'd recommend creating a simple interface which provided access to the operations you want external controls to have access to (like adding, editing, removing). This you would pass to your controls, there by restricting what the controls can actually do and not exposing unnecessary functionality to them (you wouldn't one of them to remove you main panel ;)).
When you want to remove a selected task, you click the appropriate button, it calls the appropriate "remove" method on your model.
You implementation would then find the selected item (which I assume you either maintain a reference to or have some means to find) and simply remove it from it's parent container.

How to execute an action on a component with a button of an external object?

It was hard to word the title for this one, but here's the explanation:
I have a menu bar that I'm adding as an external object from my MenuBar.java that extends JMenuBar to my main program file APP.java that extends JFrame.
MenuBar and a JPanel (which is in my main program file, APP.java) are added to the JFrame. How do I make buttons from the MenuBar perform actions on the JPanel.
Here's how my JMenuItem objects look like right now in MenuBar.java:
item = new JMenuItem("New);
item.setMnemonic(KeyEvent.VK_N);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
ActionEvent.ALT_MASK));
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JLabel block = new JLabel();
block.setPreferredSize(new Dimension(120, 160));
//***This is where I run into a problem... I want to add this JLabel to my JPanel in
// the main file, and I also want to revalidate/repaint the JPanel to take show
// the new JPanels as they're added.....
}
});
file.add(item);
I'm not sure if I need to extend my APP to implement ActionListener.... but then I am not sure what to do afterwards.
EDIT:
Well, I was able to perform the intended action by making my content panel public and static, thus making it available without instantiating the APP object. And then I was able to implement this code into my actionPerormed methods in ActionListeners:
APP.content.add(new Thumb());
APP.content.validate();
Thumb() method creates a new JLabel;
Hopefully this won't mess up my stuff later on down the line, being that my content panel is static now.
This is hard to answer.
I would use setAction(Action) (indirectly). One can make an Action as child of AbstractAction, and an Action can hold its text, an icon, mnemonic key and more.
One typical usage is a JTextPane that provides a Action[] getActios() and those actions might be added to the menu bar or a JToolBar.
Please look up some code samples.
I leave it at this half of an answer.
An intro.
It would depend on what actions you want to perform, but the overall solution is the same. You need to pass a reference of the object of the object you want to work with to the menu class.
If you can, its better to pass a model of interace, limiting your actions to only performing work you really want them to

Get contents of Java Swing Component

I need to get contents of JPanel component (one of tabs), which a part of JTabbedPane. From class where JTabbedPane is defined there is an event listener which gets current selected tab (on state change).
Here is sample code:
...
Component tab = jTabbedPane1.getSelectedComponent();
...
I need to get all components in that tab. For example:
Component[] comps = tab.getComponents(); // obviously it didn't work
I need this, because I have to disable/enable some buttons depending user rights.
Better to use your own class with the buttons as fields and then be able to directly obtain references to the buttons held by the components, or better still, be able to interact with public mutator methods that can change the button state for you (you want to expose the least amount of information to the outside world as possible -- to encapsulate your information), something like:
// assuming the JButtons are in an array
public void setButtonEnabled(int buttonIndex, boolean enabled) {
buttonArray[buttonIndex].setEnabled(enabled);
}
Or same example for if the buttons are in a HashMap that uses the button text String as the key:
// assuming the JButtons are in an hashmap
public void setButtonEnabled(String buttonMapKey, boolean enabled) {
JButton button = buttonMap.get(buttonMapKey);
if (button != null) {
button.setEnabled(enabled);
}
}
Also, your code suggests that you're using NetBeans to create your Swing code. I suggest that you avoid doing this until you fully understand Swing, that instead you use the tutorials to help you to learn to create Swing by hand as this will give you a much better understanding of the underpinnings of Swing. Then later when you understand it well, sure, use code-generation software to speed up your development time, only now you'll know what it's doing under the surface and you will be able to control it better.
Luck!
I would encapsulate this logic in the panel.
How about extending JPanel to create a RoleAwareButtonPanel that contains your buttons. You could then pass in some kind of Role object and have your panel enable/disable buttons as appropriate.
class Role {
private boolean canCreate;
private boolean canEdit;
//etc...
//getters and setters
}
class RoleAwareButtonPanel extends JPanel {
private JButton createButton;
private JButton editButton;
//other stuff you need for your panel
public void enableButtonsForRole(Role role) {
createButton.setEnabled(role.canCreate());
editButton.setEnabled(role.canEdit());
}
}

Categories

Resources