Bölüm 8: Grafikler

Bölüm 8: Grafikler · Çalışma Soruları
Olay güdümlü programGraphicsJFrame ve JPanelPoint, Color, FontYerleşimFare olaylarıEDTMetin bileşenleriPara üstü
Sercan KÜLCÜ

Çoktan Seçmeli · Grafik Programlama

Soru 1: main Bittikten Sonra

Bir Swing programının main metodu pencereyi kurup setVisible(true) çağırdıktan sonra bitiyor. Bundan sonra ne olur?

B: GUI programları olay güdümlüdür: main yalnızca arayüzü kurar. Pencere açıldıktan sonra olay iş parçacığı (EDT, arka plan olmayan bir iş parçacığı) olay kuyruğunu bekler; tıklama gibi her olayda ilgili dinleyiciyi çağırır. JVM, bu iş parçacığı çalıştıkça kapanmaz.

Hesap Sorusu · Grafik Programlama

Soru 2: Koordinatlar ve Sınırlayıcı Dikdörtgen

Bir panelde şu çizimler yapılıyor. (a) g.drawOval(30, 20, 80, 40) elipsinin merkezi hangi noktadır, en alttaki pikseli hangi y'dedir? (b) Merkezi (120, 80), yarıçapı 30 olan dolu daireyi çizen fillOval çağrısını yazın. (c) g.drawRect(20, 30, 50, 40) çerçevesinin sağ alt köşe pikseli hangi noktadır?

Cevabı göster
  • (a) Elips, sol üst köşesi (30, 20), boyutu 80 × 40 olan dikdörtgene sığar: merkez (30 + 40, 20 + 20) = (70, 40). y aşağı doğru büyüdüğü için en alt nokta y = 20 + 40 = 60'tır (piksel olarak denendi).
  • (b) g.fillOval(120 - 30, 80 - 30, 60, 60), yani fillOval(90, 50, 60, 60): parametreler merkez değil, sınırlayıcı karenin sol üst köşesi ve boyutudur.
  • (c) (70, 70): drawRect x..x+en ve y..y+boy arasını çizer (çerçeve en + 1 piksel geniştir). Bir BufferedImage üzerinde denendi: (70, 70) boyalı, (71, 70) boş.

Adım Adım Çalıştırma · Giriş Yasak İşareti

Soru 3: İşaret 240 × 180 Panelde

Giriş yasak işaretini çizen paintComponent 240 × 180 piksellik bir panelde çalışıyor (arka plan yeşil). Değişkenler ve üç çizim çağrısının argümanları ne olur?

Zemin arka plan rengiyle (yeşil) boyanır.

Merkez: (240 / 2, 180 / 2) = (120, 90).

min(120, 90) − 5 = 85: kısa kenara göre seçilir.

85 × 0,9 = 76,5; (int) ondalığı atar: 76.

76 × 1,4 = 106,4 → 106; 76 × 0,35 = 26,6 → 26 (yuvarlama değil, kesme).

fillOval(35, 5, 170, 170): beyaz daire; kesikli kare sınırlayıcı dikdörtgendir.

fillOval(44, 14, 152, 152): kırmızı daire beyazın üstüne boyanır, 9 piksellik halka kalır.

bw / 2 = 53, bh / 2 = 13 → fillRect(67, 77, 106, 26). Sonradan çizilen en üstte görünür.

super.paintComponent(g);
Point c = new Point(getWidth() / 2,
    getHeight() / 2);
int r = Math.min(getWidth() / 2,
    getHeight() / 2) - 5;
int r2 = (int) (r * 0.9);
int bw = (int) (r2 * 1.4);
int bh = (int) (r2 * 0.35);
g.setColor(Color.WHITE);
g.fillOval(c.x - r, c.y - r, 2 * r, 2 * r);
g.setColor(Color.RED);
g.fillOval(c.x - r2, c.y - r2, r2 * 2, r2 * 2);
g.setColor(Color.WHITE);
g.fillRect(c.x - bw / 2, c.y - bh / 2, bw, bh);

Çoktan Seçmeli · Pencere ve Panel

Soru 4: Kapatma Düğmesi

JFrame oluşturulup boyutu verildi ve setVisible(true) çağrıldı; setDefaultCloseOperation hiç çağrılmadı. Kullanıcı pencerenin × düğmesine basınca ne olur?

C: Varsayılan davranış HIDE_ON_CLOSE'dur: pencere yalnızca görünmez olur, JVM kapanmaz. Programın kapanması için setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) çağrılır. Kapatmayı tümüyle engellemek DO_NOTHING_ON_CLOSE ile olur.

Çoktan Seçmeli · Pencere ve Panel

Soru 5: İçerik Bölmesine İki Düğme

Pencereye bölge belirtmeden iki düğme ekleniyor. Pencere açılınca ne görünür?

JFrame f = new JFrame("Deneme");
f.add(new JButton("Bir"));
f.add(new JButton("İki"));
f.setSize(300, 200);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);

D: JFrame'in içerik bölmesi BorderLayout kullanır; bölge verilmeyen add CENTER'a ekler. Her bölgede tek bileşen yerleşir: son eklenen kazanır. Bir düğmesi kapsayıcıda kalır ama boyutu 0 × 0 olur. Yan yana dizilim FlowLayout'un (JPanel'in varsayılanı) davranışıdır. Aynı yerleşim 300 × 200 bir BorderLayout panelinde denendi: İki (0, 0, 300, 200), Bir 0 × 0.

Çıktı Sorusu · Çizim Araçları

Soru 6: Point Referansı ve Color

Program hangi üç satırı yazdırır?

Point p = new Point(10, 20);
Point q = p;
q.translate(5, 5);
p.setLocation(p.x * 2, p.y);
System.out.println(p + " " + (q == p));
System.out.println(q.distance(30, 29));
Color k = new Color(200, 100, 50).darker();
System.out.println(k.getRed() + " " + k.getGreen()
    + " " + k.getBlue());
Cevabı göster
java.awt.Point[x=30,y=25] true
4.0
140 70 35
  • Point q = p; yeni nokta oluşturmaz: iki değişken aynı nesneyi gösterir. translate(5, 5) → (15, 25); setLocation(15 * 2, 25) → (30, 25). q == p true.
  • (30, 25) ile (30, 29) arası 4.0 (distance double döndürür).
  • darker() her bileşeni 0,7 ile çarpıp tam sayıya keser: 140, 70, 35. Asıl renk değişmez, yeni bir Color döner.

Çoktan Seçmeli · Çizim Araçları

Soru 7: Kalın ve İtalik

Font f = new Font("Serif", Font.BOLD | Font.ITALIC, 20); için f.getStyle() ne döndürür?

A: Font.PLAIN = 0, Font.BOLD = 1, Font.ITALIC = 2 bit bayraklarıdır; | (bit düzeyinde VEYA) ikisini birleştirir: 1 | 2 = 3. isBold() ve isItalic() ikisi de true döner; punto ayrı bir parametredir (getSize() = 20).

Adım Adım Çalıştırma · Yerleşim Yöneticileri

Soru 8: BorderLayout Bölgeleri

300 × 200 piksellik panele tercih edilen boyutları verilmiş bileşenler ekleniyor (kutu(en, boy) o boyutu tercih eden bir JPanel döndürür). Her eklemeden sonra bileşenlerin konumu ve boyutu ne olur?

Boş panel: 300 × 200, bölgeler arası boşluk 0.

kuzey

Kuzey tüm genişliği alır; yüksekliği tercih edilen boydur (30). Tercih edilen en (100) yok sayılır.

kuzeygüney

Güney en alta, tam genişlikte: y = 200 − 20 = 180.

kuzeygüneybatı

Batı, kuzey ile güney arasındaki yüksekliği alır: 200 − 30 − 20 = 150; eni tercih edilen 60.

kuzeygüneybatıdoğu

Doğu sağ kenara: x = 300 − 40 = 260.

kuzeygüneybatıdoğumerkez

Bölge verilmedi: CENTER. Tercihi (10 × 10) önemsizdir; kalan alanın tamamını alır: 200 × 150.

kuzey 2güneybatıdoğumerkez

NORTH'a ikinci ekleme ilkinin yerini alır. Yeni kuzey 40 piksel yüksek; batı, doğu ve merkez 10 piksel aşağı kayar ve kısalır. Eski kuzey panelde kalır ama yerleşime katılmaz.

JPanel p = new JPanel(new BorderLayout());
p.setSize(300, 200);
p.add(kutu(100, 30), BorderLayout.NORTH);
p.add(kutu(100, 20), BorderLayout.SOUTH);
p.add(kutu(60, 50), BorderLayout.WEST);
p.add(kutu(40, 50), BorderLayout.EAST);
p.add(kutu(10, 10));
p.add(kutu(80, 40), BorderLayout.NORTH);

Çoktan Seçmeli · Yerleşim Yöneticileri

Soru 9: GridLayout'ta Beşinci Düğme

new GridLayout(2, 3) kullanan 300 × 120 piksellik bir panele sırayla 5 düğme ekleniyor. 5. düğmenin konumu ve boyutu (x, y, en, boy) nedir?

B: GridLayout paneli eşit hücrelere böler: 300 / 3 = 100 en, 120 / 2 = 60 boy. Düğmeler satır satır yerleşir: 1–3 üst satırda, 4 alt satırın ilk, 5 ikinci hücresinde: x = 100, y = 60. Altıncı hücre boş kalır; hücre boyutu bileşen sayısına göre değişmez.

Çoktan Seçmeli · Fare Olayları

Soru 10: Sürükleme Hiç Gelmiyor

Panel üzerinde sürükleyerek çizim yapılmak isteniyor ama mouseDragged hiç çalışmıyor; mousePressed ise çalışıyor. Neden?

MouseAdapter ma = new MouseAdapter() {
  public void mousePressed(MouseEvent e) {
    // yeni eğri başlat
  }
  public void mouseDragged(MouseEvent e) {
    // son eğriye nokta ekle, repaint()
  }
};
panel.addMouseListener(ma);

C: MouseAdapter hem MouseListener hem MouseMotionListener metotlarını boş gövdelerle içerir, ama kayıt arayüze göre yapılır: addMouseListener yalnızca basma, bırakma, tıklama, giriş ve çıkış olaylarını iletir. Olay doğrudan panele gönderilerek denendi: yalnız addMouseListener ile mouseDragged 0 kez, panel.addMouseMotionListener(ma) eklenince 1 kez çağrıldı.

Çıktı Sorusu · Çizim Programı

Soru 11: Eğriler ve drawLine Sayısı

Çizim programında (her basış yeni bir eğri başlatır, her sürükleme son eğriye nokta ekler; paintComponent her eğride onceki'yi ilk nokta yapıp her nokta için bir drawLine çağırır) kullanıcı şunları yapıyor: (10, 10)'da basar, (20, 10) ve (30, 20)'ye sürükler, bırakır; (5, 5)'te basar, (6, 6)'ya sürükler, bırakır. Sonra pencere yeniden çiziliyor. egriler.size(), her eğrinin nokta sayısı ve toplam drawLine çağrısı kaçtır?

Cevabı göster
  • egriler.size() = 2: her mousePressed yeni bir iç liste ekler; mouseReleased yazılmadığı için hiçbir şey yapmaz.
  • Eğri 0: (10, 10), (20, 10), (30, 20) → 3 nokta. Eğri 1: (5, 5), (6, 6) → 2 nokta.
  • drawLine = 3 + 2 = 5: iç döngü ilk noktadan başladığı için ilk çağrı noktayı kendisiyle birleştirir (tek piksel). Görünen çizgi parçası 2 + 1 = 3'tür.

Veri (noktalar) saklandığı için pencere her yeniden çizildiğinde aynı resim oluşur.

Çoktan Seçmeli · Fare Olayları

Soru 12: invokeLater ve invokeAndWait

Bu satırlar main iş parçacığında çalışıyor. Ekrandaki harflerin sırası için hangisi kesindir?

SwingUtilities.invokeLater(
    () -> System.out.println("B"));
System.out.println("A");
SwingUtilities.invokeAndWait(
    () -> System.out.println("C"));
System.out.println("D");

D: invokeLater işi olay kuyruğuna koyup hemen döner; B'nin A'dan önce mi sonra mı yazılacağını zamanlayıcı belirler. Olay kuyruğu sıralıdır: B, C'den önce çalışır. invokeAndWait C bitene kadar bekler, bu yüzden D en sondadır. Pencere gerekmez; denemelerde ABCD görüldü ama bu bir garanti değildir.

Çoktan Seçmeli · Metin Bileşenleri

Soru 13: Lambdada Sayaç

Düğmeye her tıklanışta sayacı artırmak için şu kod yazıldı. Ne olur?

public static void main(String[] args) {
  int sayac = 0;
  JButton d = new JButton("Tıkla");
  d.addActionListener(e -> sayac++);
}

A: Derleyici iletisi: local variables referenced from a lambda expression must be final or effectively final. Lambda yerel değişkenin değerini yakalar, değiştiremez. Çözüm: sayac'ı sınıfın alanı (field) yapmak; alanlar lambda içinden değiştirilebilir.

Çıktı Sorusu · Metin Bileşenleri

Soru 14: JTextArea ve JTextField

Program hangi üç satırı yazdırır?

JTextArea a = new JTextArea("x");
a.append("\ny");
a.append("\n");
System.out.println(a.getLineCount());
a.setText("tek");
a.append(" satır");
System.out.println(a.getText() + " "
    + a.getLineCount());
JTextField f = new JTextField(10);
f.setText(" 42 ");
int n = Integer.parseInt(f.getText().trim());
System.out.println(n + 1);
Cevabı göster
3
tek satır 1
43
  • Metin "x\ny\n" oldu: iki satır sonu, üç satır (sonuncusu boş). getLineCount() satır sonu sayısının bir fazlasıdır.
  • setText eski içeriği siler; append sona ekler: "tek satır", satır sonu yok → 1.
  • getText() her zaman String döndürür; boşluklar trim() ile atılmasaydı parseInt NumberFormatException fırlatırdı. 42 + 1 = 43.

Çıktı Sorusu · Harf Çevirici

Soru 15: Büyük Harf ve Yerel Ayar

Program hangi dört satırı yazdırır?

String s = "Kış İzmir";
Locale tr = new Locale("tr");
System.out.println(s.toUpperCase(tr));
System.out.println(s.toLowerCase(tr));
System.out.println(s.toUpperCase(Locale.ENGLISH));
System.out.println(s);
Cevabı göster
KIŞ İZMİR
kış izmir
KIŞ İZMIR
Kış İzmir
  • Türkçe kuralları: i → İ, ı → I; İ → i, I → ı.
  • İngilizce kuralları: ı → I, i → I, İ değişmeden kalır: İZMIR. Bu yüzden metin dönüştürücüde yerel ayarı açıkça vermek gerekir.
  • Dizgiler değiştirilemez: toUpperCase yeni bir dizgi döndürür; s hâlâ "Kış İzmir"'dir. Düğme dinleyicisinde sonucu setText ile geri yazmak bu yüzden gerekir.

Adım Adım Çalıştırma · Para Üstü Uygulaması

Soru 16: raporuGuncelle: 187 Kuruş

Kullanıcı miktar alanına 187 yazdı. raporuGuncelle rapor alanına hangi satırları yazar?

Alanda 187 yazıyor; metin tam sayıya çevrilir.

setText raporu sıfırdan başlatır.

187 / 50 = 3 adet (tam sayı bölmesi).

Kalan: 187 % 50 = 37.

37 / 25 = 1 adet (tam sayı bölmesi).

Kalan: 37 % 25 = 12.

12 / 10 = 1 adet (tam sayı bölmesi).

Kalan: 12 % 10 = 2.

2 / 5 = 0 adet (tam sayı bölmesi).

Kalan: 2 % 5 = 2.

2 / 1 = 2 adet (tam sayı bölmesi).

Kalan: 2 % 1 = 0. Döngü biter: 3 + 1 + 1 + 0 + 2 = 7 madeni para.

void raporuGuncelle() {
  try {
    int miktar = Integer.parseInt(
        metin.getText(0, metin.getLength()));
    int[] dizi = {50, 25, 10, 5, 1};
    rapor.setText(miktar + " kuruş yapmak için kullanılacaklar:\n");
    for (int x : dizi) {
      rapor.append(miktar / x + " " + x + " kuruş\n");
      miktar %= x;
    }
  } catch (NumberFormatException e) {
    rapor.setText("Tam sayı değil veya aralık dışında");
  } catch (Exception e) {
    rapor.setText(e.toString());
  }
}

Kod Yazma · Grafik Programlama

Soru 17: Hedef Tahtası

JPanel'den türeyen bir sınıfın paintComponent metodunu yazın: panelin ortasında, kısa kenara göre ölçeklenen (kenarda 10 piksel pay), içten dışa kırmızı-beyaz sırayla 4 halkalı bir hedef çizsin. 220 × 150 panelde hangi dört fillOval çağrısı yapılır?

Cevabı göster
@Override
public void paintComponent(Graphics g) {
  super.paintComponent(g);
  int cx = getWidth() / 2, cy = getHeight() / 2;
  int r = Math.min(cx, cy) - 10;
  for (int i = 0; i < 4; i++) {
    int ri = r - i * r / 4;   // büyükten küçüğe
    g.setColor(i % 2 == 0 ? Color.RED : Color.WHITE);
    g.fillOval(cx - ri, cy - ri, 2 * ri, 2 * ri);
  }
}

220 × 150: cx = 110, cy = 75, r = 65. i * r / 4 soldan sağa hesaplanır (önce çarpma): ri = 65, 49, 33, 17 → fillOval(45, 10, 130, 130), (61, 26, 98, 98), (77, 42, 66, 66), (93, 58, 34, 34). Büyük daire önce çizilmelidir; küçükten büyüğe çizilseydi en son çizilen büyük daire hepsini örterdi.

Hata Bulma · Çizim Programı

Soru 18: Üç Hata

Panel derleniyor ama eğriler görünmüyor, eski çizim artıkları kalıyor ve ilk sürüklemede istisna fırlıyor. Üç hatayı bulun.

class Cizim extends JPanel {
  List<List<Point>> egriler = new ArrayList<>();
  MouseAdapter m = new MouseAdapter() {
    public void mousePressed(MouseEvent e) { egriler.add(new ArrayList<>()); }
    public void mouseDragged(MouseEvent e) {
      egriler.get(egriler.size()).add(e.getPoint()); repaint(); }
  };
  Cizim() { addMouseListener(m); addMouseMotionListener(m); }
  public void paintcomponent(Graphics g) {
    for (List<Point> eg : egriler)
      for (int i = 1; i < eg.size(); i++)
        g.drawLine(eg.get(i - 1).x, eg.get(i - 1).y, eg.get(i).x, eg.get(i).y);
  }
}
Cevabı göster
  1. paintcomponent (küçük c) yeni bir metottur, Swing onu çağırmaz; @Override bunu derlemede yakalardı.
  2. super.paintComponent(g) yok: zemin temizlenmez, artıklar kalır.
  3. Son öğe size() - 1'dedir; get(size()) IndexOutOfBoundsException fırlatır.

Son

Bölüm 8: Grafikler: Çalışma Soruları
Konu anlatımı: Grafikler sunumu · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.