简体   繁体   中英

Swing controls work under Java 6, not under Java 7

I'm performing maintenance on an existing application. The feature I'm working on used to work when compiled under Java 6, but doesn't under Java 7. I'll try to be brief.

The app has a huge JTabbedPane that composes almost the entire UI. The JTabbedPane contains a number of JPanels. Each JPanel, in turn, contains an obscene number of JComponents. The user can enter values into the controls, but if--for some reason--they want to clear out all their changes, they can select an option to "reset" the panel. The way the responsible method works is it removes the JPanel, recreates a new one of the exact same class (they all inherit from JPanel) and re-inserts it at the same index into the JTabbedPane. Simple, right?

But what actually happens is it switches to the next JPanel tab in the JTabbedPane and then a number of controls from the new panel show up overlapping the controls in the next panel. So, for example, if I had panel0 selected and wanted to reset it, it would show panel1 as selected and a whole bunch of panel0's components overlapping it.

It gets even weirder. No other tabs can be selected after this happens. It's like the UI freezes. The user has to select the current tab (ie panel1) by clicking its tab on top (which is strange because it's already selected). Then they can go to other tabs and everything acts as it should. But if they don't know the workaround, it's rather frightening. And it's just plain wrong. Reseting the panel should just show the same panel with all of the controls blank.

Here is what is done, in pseudo-code:

  1. Get the current panel
  2. Create a new instance of it
  3. Remove current panel
  4. Insert new instance
  5. Revalidate & repaint
  6. Set the selected index of the panel

Here is the actual code:

public void resetCurrentTab( int currentTabIndex ) {

   // tried using m_tabbedPane.getTabComponentAt( currentTabIndex), but that returns null
   JPanel curTab = (JPanel)m_tabbedPane.getSelectedComponent();
   if( curTab == null )
          return;
   String curTabName = curTab.getName().trim();

   // create new instance of panel
   JPanel newPanel = null;
   try {
      newPanel = curTab.getClass().newInstance();
   } catch (InstantiationException e) {
      log.equals("Could not reset tab... tab " + curTabName + " creation failed.");
      return;
   } catch (IllegalAccessException e) {
      log.equals("Could not reset tab... tab " + curTabName + " creation failed.");
      return;
   }

   if( newPanel != null ) {
      m_tabbedPane.remove( currentTabIndex );
      m_tabbedPane.insertTab( newPanel.getName(), null, newPanel, null, currentTabIndex );
      newPanel.setVisible( true );
   }


   m_tabbedPane.revalidate();
   m_tabbedPane.repaint();
   m_tabbedPane.setSelectedIndex( currentTabIndex );
}

Like I said, this works compiled under Java 6. Under Java 7, weirdness happens. I tried all the obvious things, like changing the order of the calls to revalidate(), repaint() and setSelectedIndex(), but that doesn't change the behavior. I also tried just taking out and re-adding the same JPanel just to see what would happen. I don't get the overlapping controls weirdness, but it does go and select the next JPanel (tab) in the tabbed control.

tl;dr

A feature that runs fine compiled under Java 6 doesn't work compiled under Java 7.

Any ideas?

EDIT : I traced the problem back to something else entirely. Before the user resets the tab, a method pops up a JOptionPane asking if they're sure they want to do it. It's just using the simple YES/NO version of .showConfirmDialog(). If I remove the dialog, the feature works perfectly. If I use the dialog, I get the screwy behavior.

int response = JOptionPane
   .showConfirmDialog(
      currentTab,
      confirmMsg,
      "Reload the '" + curTabName + "' Tab",
      JOptionPane.YES_NO_OPTION,
      JOptionPane.QUESTION_MESSAGE );

      if( response == JOptionPane.YES_OPTION )
         // return a value indicating to reset the panel

I tried a few different values for the first parameter, but none alter the behavior. As you can see, the dialog falls out of scope long before the resetting occurs. Still don't know why this worked under Java 6 and not 7.

Thanks for all the suggestions.

I fixed this in an unusual way, but it's an unusual bug. I removed the Panel (called curTab in the code above) in the method was previously done, then set a flag. The TabbedPane (I had to create my own, inherited from JTabbedPane) looks for the flag in a custom Paint() method. I don't do any custom painting, but in the method, I allocate the new Panel and insert it into the TabbedPane at the index the old one was removed from. Then I clear all flags and clean up everything.

Like I said, it's an unusual fix, but it's the only way I tried I could avoid the visual and functionality glitch.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM