Aktualnie jestem w trakcie tworzenia projektu, podobnego, do tego przedstawionego na poniższym filmiku:
Problem, który mnie dręczy jest co prawda złożony, ale dość prosty.
Program opiera się na wyborze odpowiednich wierszy i kolumn (czyt. zmianie kolorów). Na ten moment stworzyłem dużą liczbę paneli i ustawiłem zmiany kolorów, z wykorzystaniem Timerów. Pomimo tego, że wstępnie wszystko jest gotowe, kod wygląda nieco hmmm brzydko. Liczba if/else i zastosowanie trzech timerów wydaje mi się być wyjątkowo nieefektywną metodą. Chciałem napisać to wszystko z wykorzystaniem jednego Timera, ale wtedy liczba casów (choć wolę unikać switcha) jest przerażająca. Dla każdego Timera napisałem też oddzielny własny ActionListener. Dodam, że za wybór odpowiednich wierszy/kolumn (czyli po prostu paneli) odpowiada pojedynczy przycisk Stop. Ponieważ zmiana akcji przycisku w czasie działania programu (chodzi mi o zmianę z podstawianiem innego listenera), z moim poziomem wiedzy, nie wchodzi w grę, postanowiłem zmieniać ją poprzez zmienną pomocniczą. Dodatkowo stworzyłem kilka tablic paneli, co miało uprościć kod, ale chyba jednak zadziałało odwrotnie do zamierzonego celu. Zastanawiałem się również nad użyciem SwingWorkera, ale to chyba jeszcze bardziej zaciemniło by kod, zwłaszcza, że operacje nie są aż tak wymagające.
Kod niestety wygląda strasznie. Prosiłbym o pomoc w jego sprzątnięciu i uproszczeniu o ile to możliwe. Poniżej zamieszczam część kodu, o którą mi chodzi:
//Zmienne, w których przechowuję wszystkie panele dla danego poziomu. Wymiary mojej tabeli to 6x7
// zawiera panel górny i dolny, czyli po 3 wiersze dla każdego panelu
private final JPanel[] firstLevelPanels = new JPanel[2];
// tutaj zawarte są (osobno nie w całości jak wcześniej) 3 górne wiersze
private final JPanel[] secondLevelPanels1 = new JPanel[3];
// analogicznie 3 dolne wiersze
private final JPanel[] secondLevelPanels2 = new JPanel[3];
// 6 tabeli paneli - każda tabela to wiersz. Każdy posiada 7 paneli, czyli 7 paneli w wierszu
private final JPanel[] rowPanels1 = new JPanel[7];
private final JPanel[] rowPanels2 = new JPanel[7];
private final JPanel[] rowPanels3 = new JPanel[7];
private final JPanel[] rowPanels4 = new JPanel[7];
private final JPanel[] rowPanels5 = new JPanel[7];
private final JPanel[] rowPanels6 = new JPanel[7];
//tabela tabeli paneli. Wszystkie tabele są tutaj
private final JPanel[][] allPanels = new JPanel[9][];
private int currentlyActivePanel = 0;
private int activeAncestorPanel = 0;
private int stopCounter = 0;
private int counter = 0;
/*ActionListener dla Timera pierwszego poziomu. Zmiana koloru tła panelu, dopóty dopóki wciśnie się przycisku Stop. Aktualnie aktywny panel ma kolor żółty, a nieaktywny szary. Funkcja changeBackground dokonuje zmian koloru tła.*/
class FirstLevelAction implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
changeBackground(allPanels[activeAncestorPanel], counter);
counter = (counter+1)%2;
}
}
//Analogicznie ActionListener dla drugiego timera. Wybór z jednego z trzech wierszy
class SecondLevelAction implements java.awt.event.ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
changeBackground(allPanels[activeAncestorPanel], counter);
counter = (counter+1)%3;
}
}
//ActionListener dla Timera trzeciego. Wybór jednego pola z 6
class ThirdLevelAction implements java.awt.event.ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
changeBackground(allPanels[activeAncestorPanel], counter);
counter = (counter+1)%7;
}
}
/*Funkcja zmieniająca kolor paneli w tabeli paneli. Aktualnie aktywny panel ma kolor żółty, reszta kolor szary. PanelIndex określa, który panel jest aktywny */
private void changeBackground(JPanel[] panels, int panelIndex){
for(JPanel panel : panels){
panel.setBackground(Color.GRAY);
}
panels[panelIndex].setBackground(Color.YELLOW);
currentlyActivePanel = panelIndex;
}
/*Inicjalizacja Timera1 jest tutaj, ponieważ chcę żeby startował od początku programu. Inicjalizacja pozostałych znajduje się w funkcji obsługującej wciśnięcie Stop */
private Timer timer1 = new Timer(500, new FirstLevelAction(allPanels, activeAncestorPanel));
private Timer timer2;
private Timer timer3;
//Funkcja obsługująca wciśnięcie Stop
private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
//stopCounter jest zmienną, która określa działanie przycisku
stopCounter++;
counter = 0;
/*Wstrzymanie Timera1, zapisanie aktywnego panelu w zmiennej activeAncestorPanel, zmiana koloru aktywnego panela na szary, wyzerowanie
zmiennej określającej aktualny panel (dla każdej tabeli idzie od 0, co może być trochę kołujące). Inicjalizacja timera2 i wystartowanie timera*/
if(stopCounter == 1){
timer1.stop();
activeAncestorPanel = currentlyActivePanel + 1;
allPanels[0][currentlyActivePanel].setBackground(Color.GRAY);
currentlyActivePanel = 0;
timer2 = new Timer(500, new SecondLevelAction());
timer2.start();
}
/*Analogicznie dla timera2, z tym że określenie numeru aktywnego panela jest trochę mylące. Chodzi o to, że w tabeli allPanels znajdują się wszystkie pozostałe tabele. Z kolei w tabeli np. secondLevelPanels1 (czyli 3 wiersze z góry) numery wierszy to 0-2, podczas gdy w zmiennej allPanels są to tabele rowPanels1, rowPanels2 i rowPanels3, a odpowiadające im indeksy w tej właśnie tabeli to od 3-5.*/
else if(stopCounter == 2){
timer2.stop();
allPanels[activeAncestorPanel][currentlyActivePanel].setBackground(Color.GRAY);
activeAncestorPanel = activeAncestorPanel + activeAncestorPanel*2 + currentlyActivePanel;
currentlyActivePanel = 0;
timer3 = new Timer(500, new ThirdLevelAction());
timer3.start();
}
//Analogicznie dla timera3
else{
timer3.stop();
stopCounter = 0;
allPanels[activeAncestorPanel][currentlyActivePanel].setBackground(Color.GRAY);
activeAncestorPanel = 0;
timer1 = new Timer(500, new FirstLevelAction());
timer1.start();
}
}
Jest tego dużo, ale zapewniam nie jest to nic skomplikowanego. Po prostu jest to pisane dość łopatologicznie ze względu na małe doświadczenie. Jeśli potrzeba coś dodać lub wyjaśnić, to proszę pytać śmiało :)
<code=java></code>