Graphics2d - rysowanie na podstawie kliknięć w jButton

0

Witam, mam następujące pytanie:

piszę niezbyt skomplikowaną aplikację okienkową, której działanie ma polegać na tym, aby odczytywać plik txt z danymi, którego format każdej linii jest taki -> czas;x1;y1;x2;y2;x3;y3. Po odczytaniu pliku program ma zrobić dla danego przedziału czasowego rysować wykres na podstawie współrzędnych odczytanych punktów.

Zaprojektowałem odpowiednie klasy do odczytywania tych danych z pliku i przechowywania w postaci tablicy (klasy punkt, pomiar, pomiarLista oraz plik). Mam też plik okienko.java, w którym zaimplementowałem klasę, która ma wyświetlać okno aplikacji (wywoływane z pliku wykresRuchu.java - plik główny). Klasa okienko przechowuje nazwę pliku do odczytu i wpisany przez usera krok czasowy.
Stworzyłem layout prostego okienka:

  • po lewej stronie mam komponent JPanel
  • po prawej stronie mam 2 textBoxy do wpisania nazwy pliku oraz kroku czasowego
  • poniżej po prawej mam labelkę do wyświetlania statusu odczytania pliku (czy znaleziono dany plik etc)
  • jeszcze niżej mam 3 buttony - do umieszczenia na panelu układu współrzędnych, do czyszczenia wykresu (bez układu) i do rysowania wykresu na gotowym układzie

I moje pytanie w tym momencie jest takie: co powinienem zrobić, aby móc wykonać działania rysownicze, na podstawie klikniętego przycisku? Myślałem o zdeklarowaniu metody paint(), ale z tego co doczytałem, to metoda ta może mieć tylko argument typu Graphics2D, a nie np String opisujący co powinna rysować. Pomyślałem też o wykorzystaniu JButtonActionPerformed(ActionEvent evt), ale nie wiem jak miałbym to połączyć z Graphics2D...
Dodam, że JPanel mam zdefiniowany z poziomu kreatora wizualnego design, więc nie mam go jako nowej klasy, tylko w postaci jPanel1 = new javax.swing.JPanel();

Czekam na jakiekolwiek sugestie, które pomogą mi ruszyć z tym programem... -.- Dzięki

0

Do rysowania wykresu skorzystaj z JFreeChart

0
garainz napisał(a):

Do rysowania wykresu skorzystaj z JFreeChart

Na razie wolałbym wykorzystać Graphics2D jednak, bo muszę jeszcze tam zrobić efekt animacji rysowania wykresu w czasie.

0

Musisz w panelu do rysowania zaimplementować metodę

public void paintComponent(Graphics g){
   super.paintComponent(g);
   ...
}

Całe rysowanie musi się odbywać wewnątrz tej metody. Np. by rysować osie, dodaj w klasie pole

boolean rysujOsie = false;

W obsłudze przycisku:

rysujOsie = true;

A w metodzie paintComponent:

if(rysujOsie)
{
    drawLine(....);
    ...
}

Do pobrania od użytkownika nazwy pliku skorzystaj z klasy JFileChooser lub FileDialog, nie każ użytkownikowi wpisywać nazwy.

0

Aha rozumiem. Czyli jeśli dobrze załapałem, to obsługę różnych przycisków, do wykonywania różnego rodzaju akcji na panelu JPanel, implementuje się na zasadzie zmiany flag stanu przy kliknięciu, a nie poprzez wywoływanie metody malowania z argumentem np String?
Pytam, bo widziałem gdzieś w sieci przykład tego typu, że w metodzie paintComponent był wywołany konstruktor klasy nadrzędnej, a po nim własna metoda myPaint, która była poza paintComponent() zdefiniowana i przyjmowała różne argumenty... i nie wiem, czy ten sposób był poprawny czy też nie.

No i kwestia tego, czy żeby zamplementować tą metodę paintComponent() to muszę mieć zdefiniowany panel jawnie jako nową klasę

public class panel extends JPanel {

   @Override
   protected void paintComponent(Graphics g) {
      ...
   }

}

czy może wystarczy niejawnie w momencie jak mam wygenerowany JPanel z automatu w Netbeansie jako

jPanel1 = new jawax.swing.JPanel() {
//tutaj funkcje 
}

Drugie pytanie: jak chciałbym tym sposobem skorzystać z Graphics2D zamiast ze starszej formy Graphics, to w tych poszczególnych if-ach w paintComponent dalej normalnie wywołuję składnię Graphics2D g2 = (Graphics2D)g; itd ?

I ostatnie - dotyczące samego projektu aplikacji: czy w dobry sposób podszedłem do tematu, że w klasie w pliku okienko.java obsługuję wszystkie kliknięcia itd itd, a klasa główna z pliku wykresRuchu.java tylko wywołuje to okno? Czy może powinno być nieco inaczej, że cały mechanizm obsługi powinien być przeniesiony do pliku głównego?

0

Rzutowanie zrób tylko raz, przed if-ami:

public void paintComponent(Graphics g){
   super.paintComponent(g);
   Graphics2D g2 = (Graphics2D)g; 
   ...
}

We wspomnianych przykładach, to pewno wywoływany był konstruktor klasy nadrzędnej?

0
bogdans napisał(a):

We wspomnianych przykładach, to pewno wywoływany był konstruktor klasy nadrzędnej?

Wydaje mi się, że tak, ale głowy sobie obciąć nie dam - tyle już przykładów od wczoraj przejrzałem, że tamtego nie znajdę na szybko.

bogdans napisał(a):

W obsłudze przycisku:
rysujOsie = true;

A czy w obsłudze zdarzenia kliknięcia danego przycisku trzeba wywołać (oprócz zmiany wartości flagi) metodę repaint() ?

Jeśli ktoś mógłby jeszcze odpowiedzieć na pytanie odnośnie tego JPanelu (czy jawnie klasę tworzyć czy niejawnie można) to będę wdzięczny :)

0

A nie możesz sam sprawdzić? Możesz niejawnie.

0

Ok, rozumiem :)

Czyli na tyle, na ile zrozumiałem - klikam w przycisk -> zmieniam stan flagi (co ma zrobić) -> wywołuje się dla danej flagi metoda paintComponent(). Repaint chyba też będzie potrzebny w obsłudze zdarzeń kliknięć przycisków...

0

Tak, po każdej zmianie stanu flagi wywołaj repaint. Metody paintComponent nie wywołuje się dla flagi. Możesz (no, prawie możesz) wymusić jej wykonanie wywołując repaint, poza tym wykonuje się ona w pewnych przypadkach automatycznie, np. po każdej zmianie rozmiarów okna.

0

"Ify" są trudne w utrzymaniu, bo za chwilę będziesz chciał mieć więcej opcji przy rysowaniu i będziesz dodawał kolejne flagi i "ify", łatwo wtedy się pogubić. Proponuję zrobić jakiegoś buildera, który będzie trzymał osobne kolekcje do wykresów, osi itd. W metodzie paintComponent pobierał elementy z buildera a na event przycisków np. czyścił listę osi w builderze

0

Ok, postaram się to przemyśleć :)

Co do obsługi przycisków, to już sobie poradziłem - działa w miarę dobrze. Mam tylko drobny problem z obsługą przycisku wyczyść panel - gdy próbuję go wyczyścić, to się udaje (znika testowo narysowany prostokąt), ale gdy ponownie klikam w przycisk, który za pierwszym razem rysował ten prostokąt, to nic się nie pojawia :x

Kanwę JPanelu czyściłem i poprzez g.clearRect(...) i poprzez jPanel1.removeAll(); ale i tak nie działa ponowne rysowanie... i nie wiem zupełnie co robię źle... -.-

0

Dodam jeszcze kod:
http://pastebin.com/FkDh51kq

0

Popłynąłeś z tymi flagami :) W akcji pierwszego buttonu zabrakło

else {
this.czyscKlik= false;
...
0

Faktycznie - nie pomyślałem, że nie tylko trzeba ustawić flagę danej akcji, ale jeszcze trzeba poprzednio włączoną akcję zdezaktywować. ;) tak to jest, jak się świeżym okiem spojrzy na kod

btw co do flag, to zrobiłem w taki sposób, bo nie miałem pomysłu, jak rozwiązać sprawę obsługi kliknięć w celu rysowania oraz walidacji danych z formularza obsługującego dane wejściowe... :/

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