JFrame - prosty program z użyciem Graphics2D

0

Witam. dopiero uczę się javy. Chciałbym skumać dokładnie na jakiej zasadzie działa Aplikacja okienkowa...
Napisałem banalny program o nazwie "Pilka", ktory wyswietla na ekranie kulkę:

import javax.swing.*;
import java.awt.*;

public class Pilka extends JFrame{
    public Pilka(){
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(640, 480);
        setVisible(true);
    }
    public void paint(Graphics grafa){
        grafa.clearRect(0, 0, getSize().width, getSize().height);
        grafa.setColor(Color.red);
        grafa.fillOval(50, 50, 50, 50);
    }
    public static void main(String args[]){
        new Pilka();
    }
}

Chciałbym jednak zrobić coś takiego, aby piłka powiedzmy zmieniała kolor co 2 sekundy na jakiś inny. Domyslam sie, ze trzeba uzyc jakiejs petli. Ale gdzie jej trzeba użyc? W ktorym fragmencie kodu? Bo przypuszczam, że raczej chyba nie w metodzie paint.

1

Ja bym to jednak puścił w nowym wątku. Tzn tak:

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

import javax.swing.JFrame;

public class Pilka extends JFrame {
    private static final long serialVersionUID = 1L;

    private final Thread kolorujacyWatek;
    private Color kolor = Color.red;

    public Pilka() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(640, 480);
        setVisible(true);
//robimy sobie nowy wątek w aplikacji który będzie zmieniał kolorek
        kolorujacyWatek = new Thread(new Runnable() {

            @Override
            public void run() {
                Random r = new Random();
                while (true) { //robimy to w nieskończonej pętli
                    synchronized (kolor) { //nie jest tu konieczne ale warto pamiętać o synchronizacji jeśli dwa wątki korzystają z tego samego obiektu, w tym przypadku z koloru
                        if (r.nextBoolean()) { //jeśli wylosowaliśmy true
                            kolor = Color.blue; //to niebieski
                        } else { //jeśli false
                            kolor = Color.red; //to czerwony
                        }
                    }
                    odrysujKulke(); //po zmianie koloru odrysowujemy kulke
                    try {
                        Thread.sleep(1000); //i śpimy przez 1 sekundę
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        kolorujacyWatek.start(); //startujemy wątek który napisalismy przed chwilą
    }

    protected void odrysujKulke() {
        repaint();
    }

    @Override
    public void paint(Graphics grafa) {
        grafa.clearRect(0, 0, getSize().width, getSize().height);
        grafa.setColor(kolor);
        grafa.fillOval(50, 50, 50, 50);
    }

    public static void main(String args[]) {
        new Pilka();
    }
}
0

No działa. fajnie. Co prawda nie do końca rozumiem jeszcze zasadę działania tych wątków, tak więc muszę o tym dokładnie poczytać i przestudiować to jeszcze. Na razie dziękuję bardzo za pomoc. Jeśli nie będę jeszcze czegoś wiedział to będę pisał.
Dziękuję jeszcze raz i pozdrawiam!

1

Dodatkowo, rysowanie rób w nowym panelu, a nie na oknie. wtedy współrzędnymi 0, 0 będzie pierwsze miejsce w środku okna, a nie jeszcze na pasku tytułu.

0
Visher napisał(a)

Dodatkowo, rysowanie rób w nowym panelu, a nie na oknie. wtedy współrzędnymi 0, 0 będzie pierwsze miejsce w środku okna, a nie jeszcze na pasku tytułu.

Ok, istotna informacja dla mnie :)

Apropos tematu wątków... Poczytałem trochę o tym. I nie wiem dlaczego np. taki program napisany przeze mnie nie działa poprawnie (nie wyświetla kulki):

import java.awt.*;
import javax.swing.*;

public class Pilka extends JFrame implements Runnable{
    public Pilka(){
        setVisible(true);
        setSize(320, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setTitle("Piłka");
        Thread thread = new Thread(this);
        thread.start();
    }
    public void run(){
        repaint();
    }
    public void paint(Graphics2D grafa){
        grafa.clearRect(0, 0, getSize().width, getSize().height);
        grafa.setColor(Color.red);
        grafa.fillOval(20, 20, 100, 100);
    }
    public static void main(String[] args) {
        Pilka pilka = new Pilka();
    }
}

1

Bo metoda repaint() wywołuje metodę paint(Graphics g), a u Ciebie takiej metody nie ma.

0

O, nie wiedziałem tego. Dziękuję za pomoc.

0

Kolejny problem:
Jak zrobić właśnie rysunek na panelu... Oto mój kod:


package pilka;

import java.awt.Graphics;

public class Pilka extends javax.swing.JFrame {

    public Pilka() {
        initComponents();
    }

    @SuppressWarnings("unchecked")
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );

        pack();
    }
    public void paint(Graphics g){
        jPanel1.paint(g);
        g.clearRect(0, 0, getSize().width, getSize().height);
        g.fillOval(0, 0, 300, 300);
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new Pilka().setVisible(true);
            }
        });
    }
    private javax.swing.JPanel jPanel1;
}

Wydaje mi się, że powinno być wszystko ok, ale tak jednak nie jest. Mianowicie Narysowane kółko jest rysowane na obszarze całego okna (łącznie z paskiem, co w efekcie daje ucięcie rysunku). Dlaczego tak jest? Przecież utworzyłem panel i w metodzie paint dodałem odpowiedni kod (jPanel1.paint(g);).

1

Bu rysujesz Oval w oknie (w metodzie paint() okna!) a nie panelu? Napisz drugą klasę, dziedziczącą po JPanel i w tym swoim panelu maluj ;]

0

No i kolega znów pomógł :) dziekuje

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