如何在代号one中使用坐标布局?
How to use coordinates to layout in codename one?
因为要做桌游,想通过X轴和Y轴在屏幕上设置组件。有没有办法使用 X 和 Y 轴设置控制位置?
谢谢
是的,这是可能的,但据我所知,这不是使用代号一进行编码的标准方式。通常组件的位置由布局管理器决定:手动设置 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 位置(在本例中是随机的),FontImage 图标从上到下沿对角线移动,并且带有 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();
});
}
希望对您有所帮助。然而,像本例中那样使用自定义布局是不常见的。使用代号一制作的棋盘游戏示例是:https://github.com/codenameone/codenameone-demos/blob/master/Solitaire/src/com/codename1/apps/solitaire/Solitaire.java and https://github.com/codenameone/codenameone-demos/blob/master/CN1Poker/src/com/codename1/demo/poker/Poker.java
因为要做桌游,想通过X轴和Y轴在屏幕上设置组件。有没有办法使用 X 和 Y 轴设置控制位置? 谢谢
是的,这是可能的,但据我所知,这不是使用代号一进行编码的标准方式。通常组件的位置由布局管理器决定:手动设置 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 位置(在本例中是随机的),FontImage 图标从上到下沿对角线移动,并且带有 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();
});
}
希望对您有所帮助。然而,像本例中那样使用自定义布局是不常见的。使用代号一制作的棋盘游戏示例是:https://github.com/codenameone/codenameone-demos/blob/master/Solitaire/src/com/codename1/apps/solitaire/Solitaire.java and https://github.com/codenameone/codenameone-demos/blob/master/CN1Poker/src/com/codename1/demo/poker/Poker.java