Java - 无法在向量中收集二维数组
Java - Cannot gather 2D array inside vector
正如我在之前的(未回答的)问题中提到的,我正在制作一个可以嵌入到我的程序中的图像编辑器。所以我得出一个结论,我决定图像编辑器必须具有撤消和重做功能。所以我写了这段代码:
public Vector<Color[][]> undo = new Vector<Color[][]>();
size = 16;
public Color[][] chroma = new Color[size][size];
//These are variables
public void saveRevision(){
System.out.println("Saving: " + current);
undo.insertElementAt(chroma.clone(), current);
current++;
/*for (int i = 0; i < (undo.size()-1); i++) {
if(i > current){
undo.remove(i);
}
}*/
}
public void undo(){
if(current > 0){
System.out.println("Gathering: " + (current-1));
current--;
/*Color[][] c = undo.get(current);
for (int i = 0; i < c.length; i++) {
for (int j = 0; j < c[i].length; j++) {
System.out.print(c[i][j]);
}
System.out.println();
}*/
/*for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
chroma[i][j] = null;
}
}*/
chroma = undo.get(current);
repaint();
}
}
public void redo(){
if((undo.size()-1) > current){
System.out.println("Gathering: " + (current+1));
current++;
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
chroma[i][j] = null;
}
}
chroma = undo.get(current);
repaint();
}
}
问题是我无法从具有所有色度修订的向量写入数组。
如您所见,我尝试了所有方法,但 "chroma" 变量似乎没有改变。我做错了什么?
刚刚忘了说:Undo 和 Redo 是使用 JButton 触发的,每次释放鼠标按钮都会进行 Revision。
我建议您查看 Java Collections tutorial 并重新设计您的代码。例如 Java Vector class 被认为是过时的和弃用的(Vector 也是线程安全的,因为你可能在 EDT 上调用这个东西,从 JButton 的使用来看,没有必要这样做) .如果您有一些非常具体的(性能)要求,那么使用低级多维数组也会很有用,但我认为您的场景并非如此。
使用高级 Java 集合构造,有更简单、更易读的方法来完成您想要的。
问题可能是,要使撤消-重做工作,撤消队列必须包含不可变数据。
这意味着对 chroma
的每个更改(更改的原子组)都需要一个新的二维数组副本;贵。
解决方案是只在 undo/redo 队列中保留 更改操作 。
在Java中有实现Action接口的AbstractAction,作为编辑的例子:UndoManager。也许对此做一些研究。
(同样弃权Vector,一个ArrayList就不给注释了。)
更好的解释:
chroma[][]
是当前状态。对于 undo/redo 设施,需要将此状态更改为较早的状态。现在可以为每个时间点存储对前一时刻的撤消 整个状态 ,chroma
的副本。
更好的方法是存储两个状态之间的 change。因此,如果 chroma[47][11]
从 A
更改为 B
,则仅存储操作对:
undo: chroma[47][11] = A;
redo: chroma[47][11] = B;
这个(需要更多努力)替代方案通常更实用。
可能原来的选择更直接:保存chroma
的副本。然后通过一些用户操作分配给色度,永远不应该改变保存的状态:副本必须是不可变的=不可改变的,它的内部状态不依赖于可改变的东西。
因此,需要副本是因为:
Color[][] chroma = ...;
Color[][] falseCopied = chroma;
chroma[3][4] = c;
// Now also `falseCopied[3][4].equals(c)`.
真正的复制可以做到:
public static Color copy(Color[][] grid) {
Color[][] copied = new Color[grid.length][];
for (int i = 0; i < grid.length; ++i) {
copied[i] = Arrays,copyOf(grid[i], grid[i].length);
}
return copied;
}
这里不需要复制每一个 Color 本身,因为 Color 是 "immutable",即你不能改变它的内部状态。 color.setBlue(23)
之类的东西不存在。
正如我在之前的(未回答的)问题中提到的,我正在制作一个可以嵌入到我的程序中的图像编辑器。所以我得出一个结论,我决定图像编辑器必须具有撤消和重做功能。所以我写了这段代码:
public Vector<Color[][]> undo = new Vector<Color[][]>();
size = 16;
public Color[][] chroma = new Color[size][size];
//These are variables
public void saveRevision(){
System.out.println("Saving: " + current);
undo.insertElementAt(chroma.clone(), current);
current++;
/*for (int i = 0; i < (undo.size()-1); i++) {
if(i > current){
undo.remove(i);
}
}*/
}
public void undo(){
if(current > 0){
System.out.println("Gathering: " + (current-1));
current--;
/*Color[][] c = undo.get(current);
for (int i = 0; i < c.length; i++) {
for (int j = 0; j < c[i].length; j++) {
System.out.print(c[i][j]);
}
System.out.println();
}*/
/*for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
chroma[i][j] = null;
}
}*/
chroma = undo.get(current);
repaint();
}
}
public void redo(){
if((undo.size()-1) > current){
System.out.println("Gathering: " + (current+1));
current++;
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
chroma[i][j] = null;
}
}
chroma = undo.get(current);
repaint();
}
}
问题是我无法从具有所有色度修订的向量写入数组。 如您所见,我尝试了所有方法,但 "chroma" 变量似乎没有改变。我做错了什么?
刚刚忘了说:Undo 和 Redo 是使用 JButton 触发的,每次释放鼠标按钮都会进行 Revision。
我建议您查看 Java Collections tutorial 并重新设计您的代码。例如 Java Vector class 被认为是过时的和弃用的(Vector 也是线程安全的,因为你可能在 EDT 上调用这个东西,从 JButton 的使用来看,没有必要这样做) .如果您有一些非常具体的(性能)要求,那么使用低级多维数组也会很有用,但我认为您的场景并非如此。
使用高级 Java 集合构造,有更简单、更易读的方法来完成您想要的。
问题可能是,要使撤消-重做工作,撤消队列必须包含不可变数据。
这意味着对 chroma
的每个更改(更改的原子组)都需要一个新的二维数组副本;贵。
解决方案是只在 undo/redo 队列中保留 更改操作 。
在Java中有实现Action接口的AbstractAction,作为编辑的例子:UndoManager。也许对此做一些研究。
(同样弃权Vector,一个ArrayList就不给注释了。)
更好的解释:
chroma[][]
是当前状态。对于 undo/redo 设施,需要将此状态更改为较早的状态。现在可以为每个时间点存储对前一时刻的撤消 整个状态 ,chroma
的副本。
更好的方法是存储两个状态之间的 change。因此,如果 chroma[47][11]
从 A
更改为 B
,则仅存储操作对:
undo: chroma[47][11] = A;
redo: chroma[47][11] = B;
这个(需要更多努力)替代方案通常更实用。
可能原来的选择更直接:保存chroma
的副本。然后通过一些用户操作分配给色度,永远不应该改变保存的状态:副本必须是不可变的=不可改变的,它的内部状态不依赖于可改变的东西。
因此,需要副本是因为:
Color[][] chroma = ...;
Color[][] falseCopied = chroma;
chroma[3][4] = c;
// Now also `falseCopied[3][4].equals(c)`.
真正的复制可以做到:
public static Color copy(Color[][] grid) {
Color[][] copied = new Color[grid.length][];
for (int i = 0; i < grid.length; ++i) {
copied[i] = Arrays,copyOf(grid[i], grid[i].length);
}
return copied;
}
这里不需要复制每一个 Color 本身,因为 Color 是 "immutable",即你不能改变它的内部状态。 color.setBlue(23)
之类的东西不存在。