การสร้าง JButton แบบกำหนดเองใน Java


97

มีวิธีสร้างJButtonกราฟิกปุ่มของคุณเองหรือไม่และไม่เพียง แต่สร้างภาพภายในปุ่ม

ถ้าไม่มีมีวิธีอื่นในการสร้าง custom JButtonใน java หรือไม่?

คำตอบ:


92

เมื่อผมเป็นคนแรกที่เรียนรู้ Java เราต้องทำ Yahtzee JPanelและผมคิดว่ามันจะเย็นจะสร้างส่วนประกอบสวิงที่กำหนดเองและภาชนะแทนเพียงการวาดภาพทุกอย่างในหนึ่ง แน่นอนว่าประโยชน์ของการขยายSwingส่วนประกอบคือการมีความสามารถในการเพิ่มการรองรับแป้นพิมพ์ลัดและคุณสมบัติการช่วยการเข้าถึงอื่น ๆ ที่คุณไม่สามารถทำได้เพียงแค่มีpaint()วิธีการพิมพ์ภาพสวย ๆ อย่างไรก็ตามอาจไม่ใช่วิธีที่ดีที่สุด แต่อาจเป็นจุดเริ่มต้นที่ดีสำหรับคุณ

แก้ไข 8/6 - หากไม่ปรากฏให้เห็นจากภาพ Die แต่ละปุ่มคือปุ่มที่คุณสามารถคลิกได้ เพื่อย้ายไปDiceContainerด้านล่าง เมื่อดูที่ซอร์สโค้ดคุณจะเห็นว่าปุ่ม Die แต่ละปุ่มถูกวาดแบบไดนามิกตามค่าของมัน

ข้อความแสดงแทน
ข้อความแสดงแทน
ข้อความแสดงแทน

ขั้นตอนพื้นฐานมีดังนี้

  1. สร้างคลาสที่ขยาย JComponent
  2. เรียกตัวสร้างพาเรนต์ super()ในตัวสร้างของคุณ
  3. ตรวจสอบให้แน่ใจว่าคุณได้ดำเนินการในชั้นเรียน MouseListener
  4. ใส่สิ่งนี้ในตัวสร้าง:

    enableInputMethods(true);   
    addMouseListener(this);
    
  5. แทนที่วิธีการเหล่านี้:

    public Dimension getPreferredSize()  
    public Dimension getMinimumSize()  
    public Dimension getMaximumSize()
    
  6. แทนที่วิธีนี้:

    public void paintComponent(Graphics g)
    

จำนวนพื้นที่ที่คุณต้องใช้เมื่อวาดปุ่มของคุณถูกกำหนดโดยgetPreferredSize()สมมติgetMinimumSize()และgetMaximumSize()ส่งคืนค่าเดียวกัน ฉันไม่ได้ทดลองกับสิ่งนี้มากเกินไป แต่ขึ้นอยู่กับเลย์เอาต์ที่คุณใช้สำหรับ GUI ของคุณปุ่มของคุณอาจดูแตกต่างไปจากเดิมอย่างสิ้นเชิง

และในที่สุดรหัสที่มา ในกรณีที่ฉันพลาดอะไรไป


1
สวัสดีขอขอบคุณก่อนสำหรับรหัส! ฉันขอแนะนำให้เพิ่ม 'setActionComme (String Command)' ในโค้ดของคุณ เป็นวิธีหนึ่งในการกรองเหตุการณ์ใน Swing (แต่คุณสามารถโต้แย้งได้ว่ามี 1001 สิ่งที่สามารถเพิ่มเพื่อให้สิ่งต่างๆดีขึ้นเล็กน้อย: P)
Jason Rogers

1
ในการสร้างแม่พิมพ์ที่คุณสามารถกดได้คุณสามารถใช้ JButton แบบเก่าธรรมดา (แทนที่จะเป็นคลาสย่อยหรือสร้าง JComponent แบบกำหนดเอง) โดยใช้ประโยชน์จาก setIcon / setPressedIcon รวมถึงฟังก์ชันไอคอนอื่น ๆ ใน JButton
ControlAltDel

34

ใช่เป็นไปได้ ข้อดีหลักอย่างหนึ่งของการใช้ Swing คือความสะดวกในการสร้างและจัดการการควบคุมนามธรรม

ต่อไปนี้เป็นวิธีที่รวดเร็วและสกปรกในการขยายคลาส JButton ที่มีอยู่เพื่อวาดวงกลมทางด้านขวาของข้อความ

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ทำให้เนื้อหาของปุ่มสามารถเปลี่ยนแปลงได้ แต่เส้นขอบจะถูกวาดโดยวิธีpaintBorder getPreferredSizeวิธีนอกจากนี้ยังต้องมีการจัดการเพื่อการเปลี่ยนแปลงแบบไดนามิกสนับสนุนเนื้อหา ต้องใช้ความระมัดระวังเมื่อวัดเมตริกแบบอักษรและขนาดรูปภาพ

สำหรับการสร้างการควบคุมที่คุณสามารถวางใจได้โค้ดข้างต้นไม่ใช่แนวทางที่ถูกต้อง ขนาดและสีเป็นแบบไดนามิกใน Swing และขึ้นอยู่กับรูปลักษณ์และความรู้สึกที่ใช้ แม้แต่รูปลักษณ์โลหะเริ่มต้นก็เปลี่ยนไปในเวอร์ชัน JRE มันจะดีกว่าถ้าใช้AbstractButtonและเป็นไปตามแนวทางที่กำหนดโดย Swing API จุดเริ่มต้นที่ดีคือการดูjavax.swing.LookAndFeelและjavax.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

การทำความเข้าใจกายวิภาคของ LookAndFeel มีประโยชน์สำหรับการควบคุมการเขียน: การสร้างรูปลักษณ์และความรู้สึกที่กำหนดเอง


13

คุณสามารถลองใช้รูปลักษณ์และสัมผัสของ Synth ได้ตลอดเวลา คุณจัดเตรียมไฟล์ xml ที่ทำหน้าที่จัดเรียงสไตล์ชีทพร้อมกับรูปภาพที่คุณต้องการใช้ รหัสอาจมีลักษณะดังนี้:

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

จากนั้นไปต่อและเพิ่มปุ่ม JB ของคุณตามปกติ การเปลี่ยนแปลงเพียงอย่างเดียวคือคุณใช้เมธอด setName (สตริง) เพื่อระบุสิ่งที่ปุ่มควรแมปในไฟล์ xml

ไฟล์ xml อาจมีลักษณะดังนี้:

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

องค์ประกอบการผูกจะระบุสิ่งที่จะแมป (ในตัวอย่างนี้จะใช้รูปแบบนั้นกับปุ่มใด ๆ ที่มีการตั้งค่าคุณสมบัติชื่อเป็น "สิ่งสกปรก")

และลิงก์ที่มีประโยชน์สองสามลิงก์:

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

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


8

ฉันอาจจะไปผิดทางเป็นล้านไมล์ (แต่ฉันยังเด็กเท่านั้น: P) แต่คุณไม่สามารถเพิ่มกราฟิกลงในพาเนลจากนั้นจึงเพิ่มมูสลิสเตนเนอร์ให้กับออบเจ็กต์กราฟิกเพื่อที่ว่าเมื่อผู้ใช้บนกราฟิกการกระทำของคุณถูกกำหนดไว้ล่วงหน้า


1
สิ่งนี้จะได้ผล แต่ฉันต้องการใช้ JButton มาตรฐานมากกว่าสร้างปุ่มประเภทของฉันถ้าเป็นไปได้
Anton

7

ฉันไม่ได้พัฒนา SWING ตั้งแต่ชั้นเรียน CS แรก ๆ แต่ถ้ามันไม่ได้สร้างขึ้นมาคุณก็สามารถสืบทอดjavax.swing.AbstractButtonและสร้างของคุณเองได้ ควรจะค่อนข้างง่ายที่จะเชื่อมโยงบางสิ่งเข้ากับกรอบงานที่มีอยู่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.