O SWT je obecně známo, že neumožňuje podbarvovat tlačítka ve Windows tak, jak to dovede například v Linuxu. Nemůže za to SWT, ale Windows – ty nedovolují tuto změnu. Jak tedy tento problém vyřešit? Více najdete v článku.

Tento problém má obecně dvě řešení. Prvním z nich je vytvoření vlastního SWT tlačítka, které si nakreslíme sami a jehož všechny události obsloužíme k naší plné spokojenosti. Pokud potřebujete vlastní vzhled aplikace, pak je toto řešení dozajista to nejlepší. Na druhou stranu je s ním spojena práce v podobě vytváření grafické podoby tlačítka, změny grafiky v případě událostí jako je klik a najetí myší apod.

Druhou možností je pak využití obrázku, který bude tlačítko obarvovat. Toto řešení má hned několik výhod. Nemusíme řešit nic jiného než barvu tlačítka. Všechny ostatní “standardní” události tlačítka budeme mít k dispozici. V našem konkrétním příkladě si ukážeme, jak podbarvit tlačítko při jeho stisku tak, aby se zvýraznil “stisk” tlačítka. Tlačítko bude pak po nějakou dobu stisknuté a až po dané době se vrátí do normálního stavu.

Nejprve je tedy třeba rozšířit třídu Button a vytvořit vlastní tlačítko, které poté budeme používat:


public class OurNewButton extends Button {

    private Color pressedColor = new Color(null, 0, 255, 0);

    private Color normalColor = new Color(null, 255, 255, 255);

    private String coreText;

    ...
    
    @Override
    protected void checkSubclass() {
    // nothing - we only want subclass button
    }
}


Zde je třeba upozornit na to, že pokud děláme podtřídu nějaké SWT třídy, je třeba povolit její subclassing přetížením metody checkSubclass, která má za úkol kontrolovat nedovolený subclassing.

Jakmile máme vytvořené naše tlačítko, můžeme začít pracovat na jeho obarvení při stisku. K tomu bude třeba vytvořit tuto metodu:


private Image createImage(Color color) {
        Image image = new Image(getParent().getDisplay(), getBounds().width - 6, getBounds().height - 6);

        GC gc = new GC(image);
        gc.setBackground(color);
        gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
        gc.fillRectangle(0, 0, image.getBounds().width, image.getBounds().height);
        gc.setFont(getFont());

        if (coreText != null) {
            gc.drawText(coreText, 0, 2, true);
        }

        gc.dispose();

        return image;
    }


Tato metoda má na starosti vytvořit obrázek dané barvy pro naše tlačítko. Nejprve vytvoříme obrázek o dané velikosti. Poté ho vykreslíme na “kreslící plochu” (GC) spolu s textem, který máme uložený v proměnné coreText.

Metodu pak použijeme v konstruktoru tlačítka, kde zaregistrujeme listener, který bude reagovat na stisk tlačítka:


 addListener(SWT.Selection, new Listener() {

            public void handleEvent(Event ev) {
                if(!getSelection()) {

                    setImage(createImage(pressedColor));

                    Thread t = new Thread(new Runnable() {

                        public void run() {
                            try {
                                Thread.sleep(unpressLimit);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }

                            Display.getDefault().asyncExec(new Runnable() {

                                public void run() {
                                    setImage(createImage(normalColor));
                                };
                            });
                        }
                    });

                    t.setDaemon(true);
                    t.start();
                }
            }
        });


Tímto listenerem snadno zajístíme, že pokud tlačítko již není stisklé, pak mu přiřadíme obrázek s barvou stisku. Na každý stisk navíc navěsíme vlákno, které bude mít na starosti nastavit tlačítku normální barvu po uplynutí určitého času (unpressLimit).

Na závěr je ještě dobré zaregistrovat dispose listener pro odstranění obou používaných barev při ukončení životního cyklu tlačítka:


addDisposeListener(new DisposeListener() {

            public void widgetDisposed(DisposeEvent arg0) {
                if (pressedColor != null) {
                    pressedColor.dispose();
                }
                if (normalColor != null) {
                    normalColor.dispose();
                }
            }
        });


Jedinou malou nevýhodou tohoto řešení je, že pokud budeme na tlačítko vypisovat text, nebude se mu velikost tlačítka přizpůsobovat. Proto je v takovýchto případech nutné navíc překrýt metodu computeSize, kterou pak nastavíme požadované rozměry.

Pomocí tohoto jednoduchého návodu získáte zajímavý efekt při stisku tlačítek ve vaší SWT aplikaci.