Java'da özel bir JButton oluşturma


97

JButtonYalnızca düğmenin içindeki bir resimle değil, kendi düğme grafiğinizle bir tane oluşturmanın bir yolu var mı ?

Değilse, java'da bir özel oluşturmanın başka bir yolu var JButtonmı?

Yanıtlar:


92

Java'yı ilk öğrenirken Yahtzee'yi yapmalıydık ve her şeyi tek bir üzerine çizmek yerine özel Swing bileşenleri ve kapları oluşturmanın harika olacağını düşündüm JPanel. SwingBileşenleri genişletmenin yararı, elbette, klavye kısayolları ve diğer erişilebilirlik özellikleri için destek ekleme yeteneğine sahip olmaktır paint(). Ancak en iyi şekilde yapılmayabilir, ancak sizin için iyi bir başlangıç ​​noktası olabilir.

Düzenleme 8/6 - Resimlerden görünmüyorsa, her Die tıklayabileceğiniz bir düğmedir. Bu onu DiceContaineraşağıya taşıyacaktır . Kaynak koduna bakıldığında, her bir Die düğmesinin değerine göre dinamik olarak çizildiğini görebilirsiniz.

alternatif metin
alternatif metin
alternatif metin

İşte temel adımlar:

  1. Genişleyen bir sınıf oluşturun JComponent
  2. Çağrı ebeveyn yapıcı super()senin kurucularınızdaki
  3. Sınıf uyguladığınızdan emin olun MouseListener
  4. Bunu yapıcıya koyun:

    enableInputMethods(true);   
    addMouseListener(this);
    
  5. Şu yöntemleri geçersiz kılın:

    public Dimension getPreferredSize()  
    public Dimension getMinimumSize()  
    public Dimension getMaximumSize()
    
  6. Bu yöntemi geçersiz kılın:

    public void paintComponent(Graphics g)
    

Düğmenizi çizerken üzerinde çalışmanız gereken alan miktarı , aynı değeri getPreferredSize()varsayarak getMinimumSize()ve döndürerek tanımlanır getMaximumSize(). Bununla çok fazla deneme yapmadım, ancak GUI'niz için kullandığınız düzene bağlı olarak düğmeniz tamamen farklı görünebilir.

Ve son olarak, kaynak kodu . Bir şey kaçırmışsam diye.


1
Merhaba, önce kod için teşekkürler! Kodunuza bir 'setActionComme (String Command)' eklemenizi öneririm. Swing'deki olayları filtrelemenin yollarından biridir. (ama sonra işleri biraz daha iyi hale getirmek için eklenebilecek 1001 şey olduğunu iddia edebilirsiniz: P)
Jason Rogers

1
Basabileceğiniz bir kalıp oluşturmak için, setIcon / setPressedIcon'un yanı sıra JButton
ControlAltDel'deki

34

Evet, bu mümkün. Swing'i kullanmanın en önemli avantajlarından biri, soyut kontrollerin oluşturulma ve manipüle edilme kolaylığıdır.

İşte mevcut JButton sınıfını metnin sağına bir daire çizecek şekilde genişletmenin hızlı ve kirli bir yolu.

package test;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;

import javax.swing.JButton;
import javax.swing.JFrame;

public class MyButton extends JButton {

    private static final long serialVersionUID = 1L;

    private Color circleColor = Color.BLACK;

    public MyButton(String label) {
        super(label);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Dimension originalSize = super.getPreferredSize();
        int gap = (int) (originalSize.height * 0.2);
        int x = originalSize.width + gap;
        int y = gap;
        int diameter = originalSize.height - (gap * 2);

        g.setColor(circleColor);
        g.fillOval(x, y, diameter, diameter);
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension size = super.getPreferredSize();
        size.width += size.height;
        return size;
    }

    /*Test the button*/
    public static void main(String[] args) {
        MyButton button = new MyButton("Hello, World!");

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 400);

        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new FlowLayout());
        contentPane.add(button);

        frame.setVisible(true);
    }

}

PaintComponent'i geçersiz kılarak düğme içeriğinin değiştirilebileceğini, ancak kenarlığın paintBorder yöntemi ile boyandığını unutmayın . GetPreferredSize yöntem ayrıca içeriğe dinamik destek değişiklikleri için yönetilmesi gerekir. Yazı tipi ölçümlerini ve görüntü boyutlarını ölçerken dikkatli olunması gerekir.

Güvenebileceğiniz bir kontrol oluşturmak için yukarıdaki kod doğru yaklaşım değildir. Swing'de boyutlar ve renkler dinamiktir ve kullanılan görünüme ve hisse bağlıdır. Varsayılan Metal görünümü bile JRE sürümlerinde değişti. AbstractButton'ı uygulamak ve Swing API tarafından belirlenen yönergelere uymak daha iyi olacaktır . İyi bir başlangıç ​​noktası, javax.swing.LookAndFeel ve javax.swing.UIManager sınıflarına bakmaktır .

http://docs.oracle.com/javase/8/docs/api/javax/swing/LookAndFeel.html

http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html

LookAndFeel'in anatomisini anlamak, kontroller yazmak için kullanışlıdır: Özel Bir Görünüm ve His Oluşturma


13

Synth görünümünü ve hissini her zaman deneyebilirsiniz. Kullanmak istediğiniz herhangi bir görüntü ile birlikte bir tür stil sayfası görevi gören bir xml dosyası sağlarsınız. Kod şöyle görünebilir:

try {
    SynthLookAndFeel synth = new SynthLookAndFeel();
    Class aClass = MainFrame.class;
    InputStream stream = aClass.getResourceAsStream("\\default.xml");

    if (stream == null) {
        System.err.println("Missing configuration file");
        System.exit(-1);                
    }

    synth.load(stream, aClass);

    UIManager.setLookAndFeel(synth);
} catch (ParseException pe) {
    System.err.println("Bad configuration file");
    pe.printStackTrace();
    System.exit(-2);
} catch (UnsupportedLookAndFeelException ulfe) {
    System.err.println("Old JRE in use. Get a new one");
    System.exit(-3);
}

Oradan devam edin ve JButton'ınızı normalde yaptığınız gibi ekleyin. Tek değişiklik, düğmenin xml dosyasında neyle eşleşmesi gerektiğini belirlemek için setName (string) yöntemini kullanmanızdır.

Xml dosyası şöyle görünebilir:

<synth>
    <style id="button">
        <font name="DIALOG" size="12" style="BOLD"/>
        <state value="MOUSE_OVER">
            <imagePainter method="buttonBackground" path="dirt.png" sourceInsets="2 2 2 2"/>
            <insets top="2" botton="2" right="2" left="2"/>
        </state>
        <state value="ENABLED">
            <imagePainter method="buttonBackground" path="dirt.png" sourceInsets="2 2 2 2"/>
            <insets top="2" botton="2" right="2" left="2"/>
        </state>
    </style>
    <bind style="button" type="name" key="dirt"/>
</synth>

Buradaki bağlama elemanı, neye eşleneceğini belirtir (bu örnekte, bu stili, name özelliği "kir" olarak ayarlanmış tüm düğmelere uygulayacaktır).

Ve birkaç faydalı bağlantı:

http://javadesktop.org/articles/synth/

http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/synth.html


8

Muhtemelen yanlış yönde bir milyon mil gidiyorum (ama ben sadece gencim: P). ancak grafiği bir panele ve ardından grafik nesnesine bir fare listesi ekleyemezsiniz, böylece kullanıcı grafikte olduğunda eyleminizin önceden gerçekleştirilmiş olur.


1
Bu işe yarardı, ancak mümkünse benim türümden bir düğme oluşturmak yerine standart JButton'u kullanmayı tercih ederim.
Anton

7

İlk bilgisayar bilimleri derslerimden beri SWING geliştirmesini yapmadım, ancak yerleşik olmasaydı, sadece kendinizinkini devralabilir javax.swing.AbstractButtonve yaratabilirsiniz. Mevcut çerçeveleriyle bir şeyi birleştirmek oldukça basit olmalı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.