Tworzenie niestandardowego Jbuttona w Javie

Czy istnieje sposób na stworzenie JButton z własną grafiką przycisku, a nie tylko z obrazem wewnątrz przycisku?

Jeśli nie, to czy istnieje inny sposób na utworzenie niestandardowego JButton w Javie?

Author: Paulo Mattos, 2008-08-05

5 answers

Kiedy po raz pierwszy uczyłem się Javy, musieliśmy stworzyć Yahtzee i pomyślałem, że fajnie byłoby tworzyć niestandardowe komponenty i kontenery Swing zamiast rysować wszystko na jednym JPanel. Zaletą rozszerzenia komponentów Swing jest oczywiście możliwość dodania obsługi skrótów klawiaturowych i innych funkcji ułatwień dostępu, których nie można zrobić tylko za pomocą metody paint() wydrukuj ładny obraz. Może nie jest to jednak zrobione najlepiej, ale może to być dobry punkt wyjścia dla ty.

Edycja 8/6-jeśli nie było to widoczne na zdjęciach, każda matryca jest przyciskiem, który można kliknąć. Spowoduje to przeniesienie go do DiceContainer poniżej. Patrząc na kod źródłowy można zobaczyć, że każdy przycisk matrycy jest rysowany dynamicznie, na podstawie jego wartości.

alt text
alt text
alt text

Oto podstawowe kroki:

  1. Utwórz klasę, która rozszerza JComponent
  2. wywołaj konstruktor nadrzędny super() w swoich konstruktorach
  3. upewnij się, że klasy implementuje MouseListener
  4. Umieść to w konstruktorze:

    enableInputMethods(true);   
    addMouseListener(this);
    
  5. Zastąp te metody:

    public Dimension getPreferredSize()  
    public Dimension getMinimumSize()  
    public Dimension getMaximumSize()
    
  6. Zastąp tę metodę:

    public void paintComponent(Graphics g)
    

Ilość miejsca, z którą musisz pracować podczas rysowania przycisku, jest określona przez getPreferredSize(), zakładając, że getMinimumSize() i getMaximumSize() zwrócą tę samą wartość. Nie eksperymentowałem zbyt wiele z tym, ale w zależności od układu używasz dla GUI twój przycisk może wyglądać zupełnie inaczej.

I na koniec kod źródłowy . Na wypadek, gdybym coś przeoczył.

 85
Author: Kevin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 07:19:59

Tak, to możliwe. Jedną z głównych zalet używania swingu jest łatwość, z jaką można tworzyć abstrakcyjne elementy sterujące i nimi manipulować.

Oto szybki i brudny sposób rozszerzenia istniejącej klasy JButton, aby narysować okrąg po prawej stronie tekstu.

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

}

Zauważ, że poprzez nadpisanie paintComponent można zmienić zawartość przycisku, ale obramowanie jest malowane metodą paintBorder. Metoda getPreferredSize wymaga również do zarządzania w celu dynamicznego wspierania zmian w treści. Należy zachować ostrożność podczas mierzenia metryk czcionek i wymiarów obrazu.

Do tworzenia kontrolki, na której możesz polegać, powyższy kod nie jest poprawnym podejściem. Wymiary i kolory są dynamiczne w huśtawce i zależą od wyglądu i sposobu użytkowania. Nawet domyślny wygląd Metal zmienił się w wersjach JRE. Lepiej zaimplementować AbstractButton i dostosować się do wytycznych określone przez Swing API. Dobrym punktem wyjścia jest spojrzenie na javax.swing.LookAndFeel i javax.swing.Klasy 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

Zrozumienie anatomii LookAndFeel jest przydatne do pisania kontrolek: Tworzenie niestandardowego wyglądu

 32
Author: McDowell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-22 17:33:24

Zawsze możesz wypróbować wygląd syntezatora. Dostarczasz plik xml, który działa jako rodzaj arkusza stylów, wraz z dowolnymi obrazami, których chcesz użyć. Kod może wyglądać tak:

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

Stamtąd, idź i dodaj swój JButton, jak zwykle. Jedyną zmianą jest użycie metody setName (string), aby określić, do czego przycisk powinien mapować w pliku xml.

Plik xml może wyglądać tak:

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

Tam element bind określa do czego ma być mapowany (w ten przykład zastosuje tę stylizację do wszystkich przycisków, których właściwość name została ustawiona na "dirt").

I kilka przydatnych linków:

Http://javadesktop.org/articles/synth/

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

 12
Author: rjohnston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-22 17:28:03

Pewnie jadę milion mil w złym kierunku (ale jestem tylko Młody: P). ale nie można dodać grafikę do panelu, a następnie mouselistener do obiektu graficznego tak, że gdy użytkownik na grafice twoja akcja jest preformowana.

 8
Author: AngelOfCake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-20 15:48:56

Nie robiłem swingu od moich wczesnych klas CS, ale jeśli nie był wbudowany, możesz po prostu odziedziczyć javax.swing.AbstractButton i stworzyć swój własny. Powinno być dość proste połączenie czegoś z istniejącymi ramami.

 6
Author: John Downey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-09 09:56:03