Graphics2d - rysowanie na podstawie kliknięć w jButton

Graphics2d - rysowanie na podstawie kliknięć w jButton
LU
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 5 lat
  • Postów:96
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


Jeśli starasz się za coś wziąć, rób to z należytą starannością.
--------------------------------------------
Kupić kupon chybił-trafił 2zł, napisanie programu losującego liczby jako pierwszego programu w C++ - bezcenne :)
0

Do rysowania wykresu skorzystaj z JFreeChart

LU
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 5 lat
  • Postów:96
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.


Jeśli starasz się za coś wziąć, rób to z należytą starannością.
--------------------------------------------
Kupić kupon chybił-trafił 2zł, napisanie programu losującego liczby jako pierwszego programu w C++ - bezcenne :)
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
0

Musisz w panelu do rysowania zaimplementować metodę

Kopiuj
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

Kopiuj
boolean rysujOsie = false;

W obsłudze przycisku:

Kopiuj
rysujOsie = true;

A w metodzie paintComponent:

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

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


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
edytowany 1x, ostatnio: bogdans
LU
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 5 lat
  • Postów:96
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ę

Kopiuj
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

Kopiuj
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?


Jeśli starasz się za coś wziąć, rób to z należytą starannością.
--------------------------------------------
Kupić kupon chybił-trafił 2zł, napisanie programu losującego liczby jako pierwszego programu w C++ - bezcenne :)
edytowany 3x, ostatnio: lukusm
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
0

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

Kopiuj
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?


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
LU
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 5 lat
  • Postów:96
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 :)


Jeśli starasz się za coś wziąć, rób to z należytą starannością.
--------------------------------------------
Kupić kupon chybił-trafił 2zł, napisanie programu losującego liczby jako pierwszego programu w C++ - bezcenne :)
edytowany 1x, ostatnio: lukusm
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
0

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


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
LU
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 5 lat
  • Postów:96
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...


Jeśli starasz się za coś wziąć, rób to z należytą starannością.
--------------------------------------------
Kupić kupon chybił-trafił 2zł, napisanie programu losującego liczby jako pierwszego programu w C++ - bezcenne :)
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
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.


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
GA
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 5 lat
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

LU
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 5 lat
  • Postów:96
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... -.-


Jeśli starasz się za coś wziąć, rób to z należytą starannością.
--------------------------------------------
Kupić kupon chybił-trafił 2zł, napisanie programu losującego liczby jako pierwszego programu w C++ - bezcenne :)
GA
może flagi nie zmieniasz, a może nie wołasz repainta, kto to może wiedzieć jak nie Ty skoro tylko Ty masz kod przed oczami :)
LU
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 5 lat
  • Postów:96
0

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


Jeśli starasz się za coś wziąć, rób to z należytą starannością.
--------------------------------------------
Kupić kupon chybił-trafił 2zł, napisanie programu losującego liczby jako pierwszego programu w C++ - bezcenne :)
GA
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 5 lat
0

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

Kopiuj
else {
this.czyscKlik= false;
...
LU
  • Rejestracja:ponad 15 lat
  • Ostatnio:około 5 lat
  • Postów:96
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... :/


Jeśli starasz się za coś wziąć, rób to z należytą starannością.
--------------------------------------------
Kupić kupon chybił-trafił 2zł, napisanie programu losującego liczby jako pierwszego programu w C++ - bezcenne :)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.