Как получить уведомление о том, что ребенок в композите получил / потерял фокус - PullRequest
3 голосов
/ 01 марта 2012

У меня есть SWT Composite, который мне нужно передать в другой код, который будет добавлять детей к нему по желанию.Есть ли способ получить уведомление о том, что дочерний элемент композитного объекта получил и потерял фокус?

Просто чтобы убедиться, что все понятно, я не могу добавить слушателей для каждого дочернего элемента, поскольку я не отвечаю за создание этих элементов управления,Ребенок может быть добавлен в любое время.

Ответы [ 2 ]

5 голосов
/ 01 марта 2012

Как отметил Фавониус, вы можете перехватывать события макета, такие как SWT.Resize, чтобы определить, когда вы рисуете, и пересчитать свою дочернюю иерархию, добавив слушателей по мере необходимости. Другой вариант - просто прослушать все события фокуса и обратить внимание только на те, которые предназначены для интересующих вас элементов управления.

Display s имеют фильтры , которые, подобно слушателям, уведомляются о событиях, однако фильтры отличаются тем, что они запускаются перед слушателями, у них есть возможность отменить события, и они уведомляются для всех типа события на весь Display.

Таким образом, вы можете использовать Filter, чтобы изучить все события фокуса и определить, интересует ли вас это. Например:

public class MyControl extends Composite
{
    private final Listener focusListener;

    public MyControl(final Composite parent, final int style)
    {
        /* initialize the control... */

        focusListener = new Listener()
        {
            public void handleEvent(Event event)
            {
                if (!(event.widget instanceof Control))
                {
                    return;
                }

                boolean isOurChild = false;
                for (Control c = (Control) event.widget; c != null; c = c.getParent())
                {
                    if (c == container)
                    {
                        isOurChild = true;
                        break;
                    }
                }

                if (isOurChild)
                {
                    System.out.println("Our child is " + (event.type == SWT.FocusIn ? "focused" : "unfocused"));
                }
            }
        };

        getDisplay().addFilter(SWT.FocusIn, focusListener);
        getDisplay().addFilter(SWT.FocusOut, focusListener);

        addDisposeListener(new DisposeListener()
        {
            public void widgetDisposed(DisposeEvent e)
            {
                getDisplay().removeFilter(SWT.FocusIn, focusListener);
                getDisplay().removeFilter(SWT.FocusOut, focusListener);
            }
        });
    }
}

Запомните javadoc для предупреждений Display об использовании фильтров:

Их, как правило, следует избегать по соображениям производительности, отладки и обслуживания кода.

Очевидно, что вы смотрите на компромисс производительности в любом решении - в зависимости от того, какое приложение вы поставляете, и от рабочего процесса ваших пользователей, может иметь смысл добавить фокус-слушателей при изменении размера или больше смысла просто слушать все фокусные события и игнорировать те, которые вас не интересуют.

3 голосов
/ 01 марта 2012

Вы проверили эту ссылку: SWT: уведомить составной, что у него есть новый дочерний элемент

Согласно предложенному решению в приведенной выше ссылке, единственно возможное решение - использовать событие resize. На основании этого смотрите следующий код, который добавляет слушателя фокуса на все непосредственные дочерние узлы. Хотя само решение не очень элегантно.

Тестовый код

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class SWTApplication 
{
    public static void main(String[] args) {
        new SWTApplication().initSystem("Children Notification");
    }

    private Display display;
    private Shell shell;

    public void initSystem(String windowName)
    {
        display = new Display();
        shell = new Shell(display);
        shell.setText(windowName);
        shell.setLayout(new GridLayout(6, true));
        shell.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        final TestFocusListener listener = new TestFocusListener();

        shell.addControlListener(new ControlListener() {
            public void controlResized(ControlEvent e) {
                if(e.getSource() instanceof Shell)
                {
                    Shell s = (Shell)e.getSource();
                    Control[] children = s.getChildren();
                    for (int i = 0; i < children.length; i++) 
                    {
                        Control c = children[i];
                        c.removeFocusListener(listener);
                        c.addFocusListener(listener);
                    }
                }
            }
            public void controlMoved(ControlEvent e) {
            }
        });


        createControls();

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }

        display.dispose();
    }

    private void createControls() 
    {
        String[] name = {"a", "b", "c", "d", "e", "f"};
        for(int i=0; i<6; i++)
        {
            Button button = new Button(shell, SWT.PUSH);
            button.setText(name[i] + " button");
            button.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
            shell.setSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT));
        }
    }

    class TestFocusListener implements FocusListener
    {
        public void focusGained(FocusEvent e) {
            Object src = e.getSource();
            if(src instanceof Button)
            {
                System.out.println("Focus gained: " + ((Button)src).getText());
            }

        }
        public void focusLost(FocusEvent e) {
            Object src = e.getSource();
            if(src instanceof Button)
            {
                System.out.println("Focus lost: " + ((Button)src).getText());
            }
        }
    }

}
...