用某种表格替换嵌套的if子句

时间:2016-01-18 20:57:50

标签: java

我想创建一个简单的小awt.component,它给我一个调整大小的光标在所有4个边(以及4个角)和一个移动光标在" body"组件。

以下代码可以正常工作,但对于这样一个简单的任务而言看起来很丑陋和复杂。

@Override
public void mouseMoved(MouseEvent arg0) {
    if (interactMode != InteractivityMode.EDIT_WINDOW){
        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
        return;
    }

    // left border
    if (arg0.getX() < RESCALE_AREA) {
        if (arg0.getY() < RESCALE_AREA) {
            setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
        } else if(arg0.getY() > getHeight()-RESCALE_AREA) {
            setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR));
        } else {
            setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
        }
    // right border
    } else if (arg0.getX() > getWidth() - RESCALE_AREA) {
        if (arg0.getY() < RESCALE_AREA) {
            setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
        } else if(arg0.getY() > getHeight()-RESCALE_AREA) {
            setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
        } else {
            setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
        }
    // top border
    } else if (arg0.getY() < RESCALE_AREA) {
        setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR));
    // bottom border
    } else if (arg0.getY() > getHeight()-RESCALE_AREA) {
        setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR));
    // cursor not on the border
    } else {
        setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
    }

}

这可以用更短/更清晰/更好的方式完成吗?

是否有某种&#34;真值表&#34; thingy允许我写一些更具人类可读性和防错性的东西,如:

X < RA | X > w-RA | Y < RA | Y > h-RA | result
----------------------------------------------
  y    |   n      |  y     |  n       | NW cursor
  y    |   n      |  n     |  n       | W cursor
  y    |   n      |  n     |  y       | SW cursor
  n    |   y      |  y     |  n       | NE cursor
  n    |   y      |  n     |  n       | E cursor
  n    |   y      |  n     |  y       | SE cursor
  n    |   n      |  y     |  n       | N cursor
  n    |   n      |  n     |  n       | movement cursor
  n    |   n      |  n     |  y       | S cursor

奖励:在我看来,只要我将鼠标移动到一个像素,上面的代码就会被执行(理论上)。这似乎是相当多的计算能力..有没有另一种方法来做到这一点,或者我应该简单地停止担心并把它全部交给awt事件处理的手? :)

4 个答案:

答案 0 :(得分:3)

解决此问题的一种方法是将可能的游标存储在9个元素的数组中,并使用条件计算该数组中的索引。这样的事情:

int horzIndex = x < RA ? 0 : x > w-RA ? 2 : 1;
int vertIndex = y < RA ? 0 : y > h-RA ? 2 : 1;
return cursors[horzIndex * 3 + vertIndex];

答案 1 :(得分:2)

你可能会更好地分离XY的条件,类似于这个伪代码:

const int[] cursorTable = { NW, N, NE, W, M, E, SW, S, SE }

if X < RA, cursor_X = 0
else if X > w-RA, cursor_X = 2
else cursor_X = 1
if Y < RA, cursor_Y = 0
else if Y > h-RA, cursor_Y = 2
else cursor_Y = 1

cursor = cursorTable[cursor_Y * 3 + cursor_Y]

答案 2 :(得分:0)

我会创建一个带有以下签名的辅助方法:

setCursor(chooseCursor(
    arg0.getX(),                // x
    arg0.getY(),                // y
    RESCALE_AREA,               // top
    RESCALE_AREA,               // left
    getHeight() - RESCALE_AREA, // bottom
    getWidth () - RESCALE_AREA  // right
));

然后你可以像这样打电话给这个帮手。这提取了一些变量,因此帮助程序可以专注于核心侧检测逻辑。

int v = (y < top  ? -1 : y > bottom ? +1 : 0);
int h = (x < left ? -1 : x > right  ? +1 : 0);

那么这个辅助方法会是什么样子呢?好吧,您可以使用一些嵌套条件来隔离测试。水平检查时,如果光标在左侧,则存储-1;如果光标在右侧,则存储+1;如果光标在中间,则存储0。像这样:

private Cursor chooseCursor(int x, int y, int top, int left, int bottom, int right) {
    int v = (y < top  ? -1 : y > bottom ? +1 : 0);
    int h = (x < left ? -1 : x > right  ? +1 : 0);

    int cursor;

    switch (v*3 + h) {
        case -3 + -1: cursor = Cursor.NW_RESIZE_CURSOR; break;
        case -3 +  0: cursor = Cursor.N_RESIZE_CURSOR;  break;
        case -3 + +1: cursor = Cursor.NE_RESIZE_CURSOR; break;

        case  0 + -1: cursor = Cursor.W_RESIZE_CURSOR;  break;
        case  0 +  0: cursor = Cursor.MOVE_CURSOR;      break;
        case  0 + +1: cursor = Cursor.E_RESIZE_CURSOR;  break;

        case +3 + -1: cursor = Cursor.SW_RESIZE_CURSOR; break;
        case +3 +  0: cursor = Cursor.S_RESIZE_CURSOR;  break;
        case +3 + +1: cursor = Cursor.SE_RESIZE_CURSOR; break;

        default:
            throw new AssertionError(String.format("impossible v=%s,h=%s", v, h));
    }

    return Cursor.getPredefinedCursor(cursor);
}

然后聪明的部分正在弄清楚如何一次打开两个变量。每个变量都包含-1,0或+1。您可以逐个乘以三并将它们相加以获得介于-4和+4之间的值。该范围内有9个值,现在您可以执行一个开关来返回九个光标中的一个。

该代码如下所示:

    originalArray[5] = {9, 2, 3, 4, 15};
    // code
    // ..

答案 3 :(得分:0)

我唯一可以建议的是分别确定水平和垂直状态。结合它的一种方法是@yole使用数组。但是有点难以理解。恕我直言,更好的方法是通过位标志和从表中读取来组合。

public class Main {

    static int S = 1;
    static int N = 2;
    static int E = 4;
    static int W = 8;

    static Map<Integer, Integer> cursors = new HashMap<Integer, Integer>() {{
        put(S, Cursor.S_RESIZE_CURSOR);
        put(N, Cursor.N_RESIZE_CURSOR);
        put(S | W, Cursor.SW_RESIZE_CURSOR);
        //...
    }};

    public static void main(String[] args) {
//        int delta = 3;
//        int width = 100;
//        int height = 100;
//
//        int x = 100;
//        int y = 200;


        int pos = 0;
        if (x < delta) pos |= W;
        else if (x > width - delta) pos |= E;

        if (y < delta) pos |= N;
        else if (y > height - delta) pos |= S;

        Integer cursor = cursors.get(pos);
        if (cursor != null) {
            //setCursor
        }
    }
}