2008-08-05 48 views
85

Có cách nào để tạo JButton bằng hình ảnh nút của riêng bạn chứ không chỉ bằng hình ảnh bên trong nút?Tạo JButton tùy chỉnh trong Java

Nếu không, có cách nào khác để tạo một tùy chỉnh JButton trong java không?

Trả lời

85

Khi tôi lần đầu tiên được học Java chúng tôi bị buộc phải Yahtzee và tôi nghĩ rằng nó sẽ được mát mẻ để tạo các thành phần và vùng chứa Swing tùy chỉnh thay vì chỉ vẽ mọi thứ trên một JPanel. Lợi ích của việc mở rộng các thành phần Swing, tất nhiên, là có khả năng thêm hỗ trợ cho phím tắt và các tính năng trợ năng khác mà bạn không thể thực hiện bằng cách có phương thức paint() in một bức tranh đẹp. Nó có thể không được thực hiện theo cách tốt nhất tuy nhiên, nhưng nó có thể là một điểm khởi đầu tốt cho bạn.

Chỉnh sửa 8/6 - Nếu hình ảnh không rõ ràng, mỗi Die là một nút bạn có thể nhấp. Thao tác này sẽ di chuyển đến số DiceContainer bên dưới. Nhìn vào mã nguồn bạn có thể thấy rằng mỗi nút Die được vẽ động, dựa trên giá trị của nó.

alt text
alt text
alt text

Dưới đây là các bước cơ bản:

  1. Tạo một lớp mà kéo dài JComponent
  2. Gọi mẹ constructor super() ở nhà thầu của bạn
  3. Hãy chắc chắn rằng bạn lớp thực hiện MouseListener
  4. Đặt điều này trong các nhà xây dựng:

    enableInputMethods(true); 
    addMouseListener(this); 
    
  5. Ghi đè các phương pháp:

    public Dimension getPreferredSize() 
    public Dimension getMinimumSize() 
    public Dimension getMaximumSize() 
    
  6. Override phương pháp này:

    public void paintComponent(Graphics g) 
    

Lượng s tốc độ bạn phải làm việc khi vẽ nút của bạn được xác định bởi getPreferredSize(), giả sử getMinimumSize()getMaximumSize() trả về cùng một giá trị. Tôi đã không thử nghiệm quá nhiều với điều này, nhưng, tùy thuộc vào cách bố trí bạn sử dụng cho GUI của bạn nút của bạn có thể trông hoàn toàn khác nhau.

Và cuối cùng, source code. Trong trường hợp tôi bị mất bất cứ điều gì.

+1

Xin chào, cảm ơn ban đầu về mã! Tôi sẽ đề nghị thêm một 'setActionComme (String Command)' vào mã của bạn. nó là một trong những cách để lọc các sự kiện trong Swing. (nhưng sau đó bạn có thể lập luận rằng có 1001 điều có thể được thêm vào để làm cho mọi thứ tốt hơn một chút: P) –

+1

Bạn có thể đặt toàn bộ mã ở đây không. –

+0

Để tạo một cái chết mà bạn có thể nhấn, bạn thực sự có thể sử dụng một JButton cũ (thay vì phân lớp hoặc tạo ra một JComponent tùy chỉnh) bằng cách tận dụng lợi thế của setIcon/setPressedIcon cũng như chức năng Biểu tượng khác trong JButton – ControlAltDel

6

Tôi chưa thực hiện phát triển SWING từ các lớp CS ban đầu của tôi nhưng nếu nó không được xây dựng trong bạn chỉ có thể kế thừa javax.swing.AbstractButton và tạo của riêng bạn. Nên được khá đơn giản để dây một cái gì đó cùng với khuôn khổ hiện có của họ.

12

Bạn luôn có thể thử giao diện Synth &. Bạn cung cấp tệp xml hoạt động như một loại biểu định kiểu, cùng với bất kỳ hình ảnh nào bạn muốn sử dụng. Mã có thể trông giống như sau:

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); 
} 

Từ đó, tiếp tục và thêm JButton của bạn như bình thường. Thay đổi duy nhất là bạn sử dụng phương thức setName (string) để xác định những gì nút nên ánh xạ tới trong tệp xml.

Các tập tin xml có thể trông như thế này:

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

Yếu tố ràng buộc có quy định cụ thể để lập bản đồ những gì để (trong ví dụ này, nó sẽ được áp dụng phong cách đó để bất kỳ nút mà sở hữu tên đã được thiết lập để "bẩn ").

Và một vài liên kết hữu ích:

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

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

32

Vâng, đây là có thể. Một trong những ưu điểm chính để sử dụng Swing là sự dễ dàng mà các điều khiển trừu tượng có thể được tạo và thao tác.

Đây là cách nhanh chóng và dơ bẩn để mở rộng lớp JButton hiện có để vẽ vòng tròn ở bên phải của văn bản.

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); 
    } 

} 

Lưu ý rằng bằng cách ghi đè paintComponent rằng nội dung của các nút có thể được thay đổi, nhưng điều đó biên giới được vẽ bởi paintBorder phương pháp. Phương pháp getPreferredSize cũng cần phải được quản lý để hỗ trợ động các thay đổi đối với nội dung. Chăm sóc cần phải được thực hiện khi đo số liệu phông chữ và kích thước hình ảnh.

Để tạo điều khiển mà bạn có thể dựa vào, mã trên không phải là cách tiếp cận chính xác. Kích thước và màu sắc là năng động trong Swing và phụ thuộc vào giao diện được sử dụng. Ngay cả giao diện Kim loại mặc định đã thay đổi trên các phiên bản JRE. Sẽ tốt hơn nếu triển khai AbstractButton và tuân theo các nguyên tắc được API Swing đặt ra. Điểm khởi đầu tốt là xem các lớp học javax.swing.LookAndFeeljavax.swing.UIManager.

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

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

Hiểu giải phẫu của LookAndFeel rất hữu ích cho các văn bản điều khiển: Creating a Custom Look and Feel

8

Tôi có lẽ sẽ là một triệu dặm trong sai trực tiếp (nhưng tôi chỉ trẻ: P). nhưng bạn không thể thêm đồ họa vào một bảng điều khiển và sau đó là một mouselistener cho đối tượng đồ họa để khi người dùng trên đồ họa hành động của bạn được định dạng sẵn.

+1

. Tôi muốn sử dụng JButton tiêu chuẩn hơn là tạo một loại nút của tôi nếu có thể. – Anton

Các vấn đề liên quan