dlaczego to zamula tylko w ten sposób?

0

Opowiem w skrócie i wkleje trochę kodu:
Aplikacja składa się z paska menu, paska narzędzi i 'obszaru roboczego'. Obszar roboczy jest zbudowany z JTabbedPane zawierającego w każdej zakładce JScrollPane, a w każdym z nich są jakieś tam panele, po których można rysować (w sumie to zmieniać ich tło).

Wszystko działa ładnie pięknie poza JButtonami, które umieszczam w lewym górnym rogu każdego z JScrollPane'ów. A jest z nimi taki problem:
Przycisk ten jest odpowiedzialny za zmniejszanie do rozmiarów minimalnych paneli we wszystkich zakładkach (jeśli te rozmiary są większe). Kliknięcie go powoduje właściwy skutek w aktualnie otwartej zakładce. Jednak bezpośrednie przełączenie po tym kliknięciu na inną zakładkę powoduje ok.6sekundowe zawieszenie aplikacji (procek pracuje na maxa), po czym odzyskujemy władzę i przechodzimy do tej zakładki co ją wybraliśmy i jest tam wszystko tak jak powinno być.

Z prób zdiagnozowania kiedy takie zawieszenia występują, a kiedy nie wynika, że:
-dzieje się tak tylko przy scenariuszu wykonywanych akcji tak jak opisałem,

Nie dochodzi do 'zawieszeń' jeśli między pomiędzy kliknięciem przycisku a przejściem do innej zakładki:
-klikniemy jakiś przycisk(Jbutton,Jtogglebuton) w pasku narzędzi,
-klikniemy ponownie już otwartą zakładkę.

Wybieranie czegokolwiek z paska menu pomiędzy wspomnianymi operacjami nie chroni przed 'zawieszaniem'
Objaśnienia do kodu:

  • JButtony o których mowa należą do tablicy "rog[]"
  • przyciski paska narzędzi nie powodują w zasadzie żadnych modyfikacji 'obszaru roboczego' a jedynie zmieniają zmienne sterujące sposobem rysowania na panelach.

Myślę, że najistotniejsze fragmenty kodu to:


public mojaAplikacja()
{
(...)
 glpanel = new JPanel(new BorderLayout());
zakladka = new JTabbedPane();

	   obszarRoboczy();

	 zakladka.addChangeListener(new ChangeListener()
	 {
		 public void stateChanged(ChangeEvent event)
		 {
			aktywna_zakl = zakladka.getSelectedIndex();
			lewy=false;
			prawy=false;
			fill_podswietl_combo(zakladka.getSelectedIndex(),pieter);
		 }
	 });
zakladka.setPreferredSize( new Dimension( dostepnyY+8 , dostepnyX+31 ) );
	 zakladka.setSize( new Dimension( dostepnyY+8 , dostepnyX+31 ) );

	 srodkowy = new JPanel();	
	 srodkowy.add(zakladka);

glpanel.add(pod_przybornik, BorderLayout.NORTH);	 
     glpanel.add(srodkowy, BorderLayout.CENTER);
     
     JScrollPane calosc = new JScrollPane(glpanel);
     add(calosc);
}

   private void obszarRoboczy()
   {
	   zakladka.removeAll();
	   
	   jakiPanel();
	   System.out.println("Rozmiar panela jest="+rozmPan);
	   
	   pole = new Panelik[pieter][rozmiarX][rozmiarY];
	   space= new int[pieter][rozmiarX][rozmiarY];								
	   kwadraty= new JPanel[pieter];
	   pietro = new JPanel[pieter];
	   przewijany = new JScrollPane[pieter];
	   poziomaSkala = new skala[pieter];
	   pionowaSkala = new skala[pieter];
	   
	   rog = new JButton[pieter];
	   rogI = new ImageIcon[pieter];
	   
	   max=rozmiarX*rozmiarY*pieter;
	   System.out.println("max="+max);
	   
	   if(rozmiarX>rozmiarY)				
	   {	tab = new int[rozmiarX*30];
	   }
	   else 
	   {	tab = new int[rozmiarY*30];
	   }
	   
	   
	   for (int k=0 ; k<pieter ; k++)
	   {
		   kwadraty[k] = new JPanel();
		   kwadraty[k].setLayout(new GridLayout(rozmiarX,rozmiarY));	
		   kwadraty[k].setBounds(0,0,rozmPan*rozmiarY,rozmPan*rozmiarX);
		   
		   pietro[k] = new JPanel();
		   pietro[k].setLayout(null);
		   
		   for (int i=0 ; i<rozmiarX ; i++)				
		   {
			   for (int j=0 ; j<rozmiarY ; j++)			
			   {
					   pole[k][i][j] = new Panelik();
					   obsluga obsl = new obsluga(k,i,j);
					   pole[k][i][j].addMouseListener(obsl);
					   kwadraty[k].add(pole[k][i][j]);
			   }
		   }
		   
		   pietro[k].add(kwadraty[k]);
		   
		   przewijany[k] = new JScrollPane(pietro[k]);
		   rogI[k] = new ImageIcon("minim.gif");
		   rog[k]= new JButton();
		   rog[k].setIcon(rogI[k]);
		   rog[k].addActionListener(new ActionListener()
		   {
			   public void actionPerformed(ActionEvent e)
			   {
			 		for (int h=0 ;h<pieter ; h++ )
	 	 			{	
	 	 				pietro[h].setPreferredSize(new Dimension(rozmiarY*rozmPan,rozmiarX*rozmPan));
	 	 				kwadraty[h].setBounds(0,0,rozmiarY*rozmPan,rozmiarX*rozmPan);

	 	 				//pietro[h].revalidate();
	 	 				//pietro[h].repaint();
	 	 				
	 	 				poziomaSkala[h].setPreferredWidth(rozmPan*rozmiarY);
	 	 				poziomaSkala[h].setSkok(rozmPan);
	 	 				pionowaSkala[h].setPreferredHeight(rozmPan*rozmiarX);
	 	 				pionowaSkala[h].setSkok(rozmPan);
	 	 				
	 	 				przewijany[h].revalidate();
	 	 				przewijany[h].repaint();
	 	 			}
	 	 			zakladka.revalidate();
	 	 			zakladka.repaint();
	 	 			
	 	 			
	 	 			glpanel.revalidate();
	 	 			glpanel.repaint();
			   }
		   });
		   
		   
		   przewijany[k].setCorner(JScrollPane.UPPER_LEFT_CORNER, rog[k]);
		   
		   poziomaSkala[k] = new skala( skala.HORIZONTAL , rozmPan,stala_s,rozmPan*dostepnyY+4 );
		   pionowaSkala[k] = new skala( skala.VERTICAL , rozmPan,stala_s,rozmPan*dostepnyX+4 );
		   poziomaSkala[k].setPreferredWidth( rozmPan*rozmiarY );
		   pionowaSkala[k].setPreferredHeight( rozmPan*rozmiarX );
		   przewijany[k].setColumnHeaderView(poziomaSkala[k]);
		   przewijany[k].setRowHeaderView(pionowaSkala[k]);
		   
		   zakladka.addTab(""+k, null, przewijany[k], "Poziom "+k);
		   zakladka.setMnemonicAt(k, 48+k ); 
	   }
	   zakladka.revalidate();
	   zakladka.repaint();
   }

0

Skorzystaj z profilera - powie Ci w jakiej funkcji spędza najwięcej czasu. W NetBeans jest już wbudowany.

0

korzystam tylko i wyłącznie z Eclipse. Czy tam też jest coś w tym stylu (jak się do tego dostać) ?

0

Moim zdaniem masz nadmiarowe wywołania revalidate(). To jest nierzadko bardzo kosztowna czasowo procedura, która i tak jest wywoływana z automatu na tak małym zbiorze komponentów jak to możliwe. Jeżeli niepotrzebnie wymuszasz przeprowadzenie dodatkowych doLayout(), które nic nie zmieniają, to stąd możesz mieć te przycinki.
Dwa cytaty z javadoca revalidate:

  1. "Supports deferred automatic layout. "
  2. "This method will automatically be called on this component when a property value changes such that size, location, or internal layout of this component has been affected."
0

wywołania revalidate() i repaint(), faktycznie były nadmiarowe. Nie mniej, zamulanie ustąpiło dopiero w momencie przypisania tego actionListener'a do specjalnie powołanego w tym celu (zwykłego) przycisku znajdującego się w pasku narzędziowym.
Dlatego też uważam, że sprawa pozostaje nadal niewyjaśniona.

0

Sprawa się wyjaśniła. Przyczyną zamulania jest duża liczba komponentów/kontenerów, a dokładniej chodzi o 'focus'. Akurat w tym przypadku ominąłem to w przenosząc zrobioną funkcjonalność do paska menu do jednego z JToggleButtonów ( rozwiązaniem mogłoby być również odpowiednie ustawienie FocusSubsystem. Zainteresowanym poleca się:
http://download.oracle.com/javase/tutorial/uiswing/misc/focus.html )

Myślę, że temat można uznać za zamknięty :) .

1 użytkowników online, w tym zalogowanych: 0, gości: 1