Как использовать координаты для компоновки в codename one?

#codenameone

#codenameone

Вопрос:

Я хочу установить компонент на экране по осям X и Y, потому что мы хотим создать настольную игру. Есть ли способ установить положение элемента управления с помощью осей X и Y? Спасибо

Комментарии:

1. О создании игр с Codename One вы можете ознакомиться с руководством «Программирование мобильных казуальных игр (карточных игр) с использованием Java»: github.com/codenameone/CodenameOne/wiki/Casual-Game-Programming . Однако он немного устарел.

Ответ №1:

Да, это возможно, но, насколько я знаю, это не стандартный способ кодирования с Codename One . Обычно положение компонента определяется менеджером компоновки: ручная настройка позиций x и y имеет смысл для эффектов перехода.

Однако вы можете использовать пользовательский макет, который позволяет вам вручную выбирать положение x и y компонента. Например:

 import com.codename1.io.Log;
import com.codename1.ui.Component;
import com.codename1.ui.Container;
import com.codename1.ui.geom.Dimension;
import com.codename1.ui.layouts.Layout;

/**
 * This is a special layout that keeps components in invalid positions with
 * their preferred size: that means that a revalidate() will not change the
 * position of components, that can be set using setX() and setY(); note that
 * animateLayout() and animateUnlayout() will not work as expected. Example of
 * usage: https://gist.github.com/jsfan3/4ccb8380e43db35f54bcd9960c6d8376
 *
 * 
 */
public class InvalidLayout extends Layout {

    private boolean fixedWidth = false;
    private int maxWidth = 0;
    private int maxHeight = 0;

    /**
     * The preferred size is calculated automatically, without a minimum width
     * or a minimum height
     */
    public InvalidLayout() {
    }

    /**
     * The preferred size is fixed to the given values
     *
     * @param width
     * @param height
     */
    public InvalidLayout(int width, int height) {
        this.fixedWidth = true;
        this.maxWidth = width;
        this.maxHeight = height;
    }

    @Override
    public void layoutContainer(Container parent) {
        for (Component current : parent) {
            current.setSize(current.getPreferredSize());
        }
    }

    @Override
    public Dimension getPreferredSize(Container parent) {
        if (!fixedWidth) {
            for (Component current : parent) {
                int x = current.getX()   current.getPreferredW();
                if (maxWidth < x) {
                    maxWidth = x;
                }
                int y = current.getY()   current.getPreferredH();
                if (maxHeight < y) {
                    maxHeight = y;
                }
            }
        }
        return new Dimension(maxWidth, maxHeight);
    }

}
 

Пример использования. Как вы можете видеть, попробовав следующий код, звездочки добавляются в произвольных позициях x, y (в данном случае случайных), значок шрифта перемещается по диагонали сверху вниз, а размер контейнера с InvalidLayout автоматически адаптируется к положению содержащихся в нем элементов:

     /**
     * This code demonstrates that InvalidLayout allows to set its Components
     * in the wanted position, that is kept after a revalidate()
     */
    public void start() {
        if (current != null) {
            current.show();
            return;
        }
        Form hi = new Form("Hi World", BoxLayout.y());
        hi.add(FlowLayout.encloseCenter(new Label("Test")));
        Container invalidCnt = new Container(new InvalidLayout());
        Label test = new Label(FontImage.createMaterial(FontImage.MATERIAL_3D_ROTATION, "Button", 5));
        invalidCnt.add(test);
        hi.add(invalidCnt);
        hi.add(FlowLayout.encloseCenter(new Label("Test")));
        test.setX(0);
        test.setY(0);
        hi.show();
        hi.revalidate();
        UITimer.timer(500, true, () -> {
            int max = 60;
            int min = 0;
            Random rand = new Random();
            Label label = new Label("*");
            invalidCnt.add(label);
            label.setX(Display.getInstance().convertToPixels(rand.nextInt((max - min)   1)   min));
            label.setY(Display.getInstance().convertToPixels(rand.nextInt((max - min)   1)   min));
            test.setX(test.getX()   Display.getInstance().convertToPixels(2));
            test.setY(test.getY()   Display.getInstance().convertToPixels(2));
            hi.revalidate();
        });
    }
 

Я надеюсь, что это может помочь. Однако использование пользовательского макета, как в этом случае, необычно. Примерами настольных игр, созданных с помощью Codename One, являются: https://github.com/codenameone/codenameone-demos/blob/master/Solitaire/src/com/codename1/apps/solitaire/Solitaire.java и https://github.com/codenameone/codenameone-demos/blob/master/CN1Poker/src/com/codename1/demo/poker/Poker.java

Комментарии:

1. О моем ответе см. Раздел «Создание собственного менеджера компоновки» руководства разработчика: codenameone.com/developing-in-codename-one.html