How to control a panel nested in JtabbedPane ? - java

I have a MainJtabbedPane which contains multiple JtabbedPanes each of the JtabbedPanes contain multiple pannels.
I need to be able to access the pannels from the MainJtabbedPane.
JTabbedPane[] components = (JTabbedPane[]) Main_Tabbed_Panel.getComponents();
for(int i=0; i<components.length;i++)
{
for(int j=0;j<components[i].getTabCount();j++)
{
.....
}
}
Giving an error java.awt.component cannot be cast to javax.swing.JtabbedPane

JTabbedPane[] components = (JTabbedPane[]) Main_Tabbed_Panel.getComponents();
The getComponents() method returns an array of Components. You can't just cast them to a JTabbedPane even if you know all the components will be an instance of JTabbedPane. You need to structure your code something like:
for(Component component: main_Tabbed_Panel.getComponents())
{
if (component instanceof JTabbedPane)
{
JTabbedPane tabbePane = (JTabbedPane)component;
// do something with the tabbed pane
}
}
Also, follow Java naming conventions. Variable name should NOT start with an upper case character. (ie. "Main_Tabbed_Pane does not follow conventions).

Switch the (JTabbedPane[]) cast to (Component[]). If you hover over the getComponents() method, you'll see it returns Component[]
If you want to convert that Component[] to JTabbedPane[], you need to do it manually, as well as making sure to check for mistakes along the way (making sure its a JTabbedPane before adding it to a JTabbedPane[])
JTabbedPane[] panes = convertComponents(getComponents());
private JTabbedPane[] convertComponents(Component[] comps) {
JTabbedPane[] panes = comps.length > 0? new JTabbedPane[comps.length] : null;
if(panes != null)
for(int i = 0; i < panes.length; i++) {
if(comps[i] instanceof JTabbedPane)
panes[i] = (JTabbedPane) comps[i];
}
return panes;
}
Although this isn't the most efficient, because for each item that isn't a JTabbedPane in getComponents(), there will be an empty spot in your JTabbedPane array, which you then have to clean up.
JTabbedPane[] panes = comps.length > 0? new JTabbedPane[comps.length] : null;
This first checks if the Component[] passed through the parameters has 1 or more spaces. If not, dont bother initializing with an instance.
if(panes != null)
Since theres a chance panes could initialize as null, we much check before trying to use it
for(int i = 0; i < panes.length-1; i++) {
Since Component[] comps and JTabbedPane[] panes have the same size, it doesn't matter which length you use, as long as we know how many times to loop.
if(comps[i] instanceof JTabbedPane)
This is what I meant where I said "if the component isn't a JTabbedPane, you will have a null space in your array". This will check if it's a JTabbedPane before putting it in our panes array. If not, it's ignored completely, and that space in panes is left as null
After the loop is complete, it will return the array we just made.

Related

Why does a JLabel Component not convert into a JLabel, yet doesn't give any errors?

Okay, so I have this JFrame frame and I'm trying to load all of the components into a JLabel ArrayList. the frame has a LayeredPane and around 20 JLabels scattered across. Some of them have a different z-index/layer index
ArrayList<JLabel> labelList = new ArrayList<>();
for(Component i : frame.getComponents() ) {
if (i instanceof JLabel) {
labelList.add((JLabel) i);
}
}
System.out.println(labelList);
but when I try to print out the ArrayList, it just prints an empty Array.
When I hover over the .getComponents(), it actually shows that all of the JLabels are in fact contained in the method.
And it doesn't give out any errors either, like Component not being able to convert to JLabel etc.
edit: I did as #camickr suggested, and it show that only the contentPane is grabbed. I probably misunderstood how the .getComponents() works.
edit2 just changed the code to:
ArrayList<JLabel> labelList = new ArrayList<>();
for(Component i : layeredPane.getComponents() ) { //layeredPane being the name of the JLayeredPane, suprisingly
labelList.add((JLabel) i);
}
System.out.println(labelList.toArray().length);
And it works.
I am a very dumb indiviudal.
ArrayList<JLabel> labelList = new ArrayList<>();
for(Component i : layeredPane.getComponents() ) { //layeredPane being the name of the JLayeredPane, suprisingly
labelList.add((JLabel) i);
}
System.out.println(labelList.toArray().length);
is the solution. It didn't work due to me trying to grab everything from the frame, but the only thing on the frame was the layered Pane, where all the other components were.

JTabbedPane: Change Title from within Tab

I'm trying now for a couple of hours to optimize my user interface but I'm not getting any further right now.
I got a JTabbedPane to show datasets. There is one textfield in there with should also represent the tabs title. Right now there is a button labeled "save" which does nothing else but read this text field from the current tab and updates the tabs title. I'd love to replace this by updating the tab's title when the field is changed. I got the event listener up and running, so no problems here, but how to I get to call the JTabbedPane object?
I tried to put a JTabbedPane variable into my JPanel class and store a reference here, but this keeps crashing the moment I call the setter for this variable...
Well, not actually crashing, but it throws an exception:
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:635)
at java.util.ArrayList.get(ArrayList.java:411)
[...]
The setter is quite simple:
public void setTabContainer(JTabbedPane cont){
container = cont;
}
Any ideas?
I got the event listener up and running, so no problems here, but how to I get to call the JTabbedPane object?
You can use SwingUtilities class as follows to get the tabbed pane that is the ancestor of your text field:
JTabbedPane tabbedPane = (JTabbedPane)SwingUtilities.getAncestorOfClass(JTabbedPane.class, textField);
Then you can iterate over the tabbed pane's components in order to find the index where your text field is placed and finally update the tab's title:
for(int i = 0; i < tabbedPane.getTabCount(); i++) {
if(SwingUtilities.isDescendingFrom(textField, tabbedPane.getComponentAt(i))) {
tabbedPane.setTitleAt(i, textField.getText());
break;
}
}
See the API for:
SwingUtilities#getAncestorOfClass(Class c, Component comp)
SwingUtilities#isDescendingFrom(Component a, Component b)
JTabbedPane#getComponentAt(int index)
Try:
JTabbedPane tabbedPane = (JTabbedPane) SwingUtilities.getAncestorOfClass(JTabbedPane.class, this);
tabbedPane.setTitleAt(tabbedPane.indexOfTabComponent(this), title);
Assumes that this is the tab component, and title is the new title. Note that you must have set this as the content for the tab.
Uses:
JTabbedPane#indexOfTabComponent
JTabbedPane#setTitleAt
SwingUtilities#getAncestorOfClass
In IntelliJ IDEA's form designer each tab is a JPanel hence you can use the following method to set the title from within Java code:
public static void setTabTitle(JPanel tab, String title)
{
JTabbedPane tabbedPane = (JTabbedPane) SwingUtilities.getAncestorOfClass(JTabbedPane.class, tab);
for (int tabIndex = 0; tabIndex < tabbedPane.getTabCount(); tabIndex++)
{
if (SwingUtilities.isDescendingFrom(tab, tabbedPane.getComponentAt(tabIndex)))
{
tabbedPane.setTitleAt(tabIndex, title);
break;
}
}
}
This solution is very similar to the one given by dic19 though.

Issue with JTabbedPane

I am having problems with the following code:
public void detachTab(TabComponent tc) {
Logger.add("Detaching Tab");
for (int i = 0; i < globalTabbedPane.getTabCount(); i++) {
if (tc == globalTabbedPane.getTabComponentAt(i)) {
Logger.add("Detaching panel: " + i);
SeparateWindow sw = new SeparateWindow((JPanel) globalTabbedPane.getComponentAt(i));
sw.setVisible(true);
globalTabbedPane.remove(i);
return;
}
}
}
It simply removes a tab from a JTabbedPane and places it in a separate window. Pretty self explanitory. The issue is that the method also removes the tab below it. I dont see how this is possible. Maybe there is something im overlooking.
I've not tested this, but...
SeparateWindow sw = new SeparateWindow((JPanel) globalTabbedPane.getComponentAt(i))
Is likely adding the Component to the window, removing it from the JTabbedPane, the tabbedpane may be then be removing the associated tab, now meaning that the index positions have changed, so when you call
globalTabbedPane.remove(i);
you are now removing the following tab...
You could try getting a reference to the component, removing it and the creating the window...
JPanel pane = (JPanel) globalTabbedPane.getComponentAt(i);
globalTabbedPane.remove(i);
SeparateWindow sw = new SeparateWindow(pane);

Iterate Through Tab Components in JTabbedPane

I need to determine which tabs in a JTabbedPane need updated by determining the contents of each tab's component. From what I can determine, there is no way to iterate through each tab using the default JTabbedPane model.
Does anyone have any ideas as to what I could do in this situation?
if you use something like:
int totalTabs = tabbedPane.getTabCount();
for(int i = 0; i < totalTabs; i++)
{
Component c = tabbedPane.getTabComponentAt(i);
//other stuff
}
Could give you a start point to do what you want.
How about getTabCount() and getTabComponentAt( int index )?
use getComponentAt(int index) from container

Find components in Java's GUI hierarchy

With this code I am able to find what tab is selected but I need to do stuff with what is inside the tab. How do I work with the hierarchy?
EditPane.addChangeListener(new ChangeListener() {
// This method is called whenever the selected tab changes
public void stateChanged(ChangeEvent evt) {
JTabbedPane pane = (JTabbedPane)evt.getSource();
// Gets current tab
int sel = pane.getSelectedIndex();
}
});
The component that is inside the tab is a JScrollPane.
You don't need the index of the pane, you need the component selected underneath.
use getSelectedComponent() - e.g.
JTabbedPane pane = (JTabbedPane)evt.getSource();
JComponent myComponent = pane.getSelectedComponent();
To clarify your original goal, you want to manipulate the client object living in the JScrollPane. You're missing some objects.
in your JScrollPane you need to invoke getViewport().getViewportView() from the ScrollPane. (Source: http://download.oracle.com/javase/tutorial/uiswing/components/scrollpane.html )
# Dasdasd
I already checked it out but it only returns ViewPorts and ScrollBars
yes that correct, (probalby there you put JPanel) then you have to repeats your steps again, until as you will not find JPanel into ViewPort, that's possible get JComponents another way(s), but this is very good lesson for Hierarchy of JComponents
Component[] components = xxx.getComponents();
for (int i = 0, l = components.length; i < l; i++) {
if (components[i] instanceof JScrollPane) {
JScrollPane scr = (JScrollPane) components[i];
Component[] components1 = scr.getComponents();n

Categories