【问题标题】:javafx drag and drop control target layoutjavafx拖放控制目标布局
【发布时间】:2019-11-07 18:58:53
【问题描述】:

我们正在尝试实现这种布局,骰子行是文本字段,当单击随机按钮时,骰子一侧的一个字母会填充其中一个字母
我们有一个由 duh TextFields 组成的 Target TextField。
当用户将其中一个骰子拖到目标上时,目标就会被填充。
问题是 Source 与 Target 的关系是 1 对 1,用户事先不知道源需要放在哪里。
接下来,我们尝试使用 Button 来表示骰子并将 Button 拖放到作为 AnchorPane 的 newPane。当我们尝试添加第二个按钮时,尝试将重复的子项添加到窗格时出现错误

问题是
1. 我们可以有源到目标的一对多关系吗?
如果是这样,我们如何编码?如果可能的话,它看起来像是不真实的代码行

  1. 如何克服使用 newPane 概念的问题?

  2. 或者有更好的设计方法吗?
    我们知道我们可以单击 Button 并构建一个单词并将其添加到 ListView 中,这不是我们想要的。

我们将使用 Button 的代码发布到它可以工作的 newPane,但是当我们为第二个 Button 复制此代码时,我们会收到上述错误

    @Override
public void initialize(URL url, ResourceBundle rb) {

    // Add mouse event handlers for the source
    btnOK.setOnMousePressed((MouseEvent event) -> {
        btnOK.setMouseTransparent(true);
        event.setDragDetect(true);
    });

    btnOK.setOnMouseReleased((MouseEvent event) -> {
        btnOK.setMouseTransparent(false);
    });

    btnOK.setOnMouseDragged((MouseEvent event) -> {
        event.setDragDetect(false);
    });

    btnOK.setOnDragDetected((MouseEvent event) -> {
        btnOK.startFullDrag();
    });

    // Add mouse event handlers for the target
    // =======================================
     newPane.setOnMouseDragEntered((MouseDragEvent event) -> {
    });
    btnOK.setOnMouseDragEntered((MouseDragEvent event) -> {
    });
    newPane.setOnMouseDragOver((MouseDragEvent event) -> {
    });

    newPane.setOnMouseDragReleased((MouseDragEvent event) -> {
    System.out.println(event.getX());
    System.out.println(event.getY());
    double h = event.getX();
    double v = event.getY();
    newPane.getChildren().add(btnOK);
    btnOK.setLayoutX(h);
    btnOK.setLayoutY(v);
        t1.setText(s1.getText());
        t1.setStyle("-fx-background-color: lightblue;");
        //newPane.getChildren().add(s1);
    });
    tosswordPane.setOnMouseDragExited((MouseDragEvent event) -> {
    });
}

这是我们正在尝试实现的布局的屏幕截图

【问题讨论】:

  • 你是如何尝试使用第二个按钮的?
  • @Grendel 我们只是复制并粘贴 btnOK 并使用新的 Button id btnNO 更改变量而不是创意命名。我们甚至尝试使用 event2 代替 event 没有运气因为代码失败我们没有发布它抱歉
  • 我不确定我是否理解您想要完成的任务。问题仅仅是用户没有指示将骰子拖到哪里吗?如果是这样,那么只要在骰子上检测到拖动,您就可以为目标设置不同的样式。
  • @Slaw 我们想使用目标文本字段,因此当您拖动 W 时,如果源和目标同步,则位置是有效的,但如果您想拖动 O,您需要知道O 目标位于 W 下方,如果您想将 R 拖到 W 下方的位置,这是不可能的,因为 R 没有该位置作为目标 假设您有 3 个骰子,并且您正在用手定位骰子你可以把它们放在你不喜欢的地方,因为源和目标是一对一的关系类型的人工智能问题
  • @Slaw 我们考虑过在拖动 Source 的同时将鼠标悬停在节点 id 上并使用该 id 设置 Target 但现在确定如何获取任何节点的 id 就像我们需要使所有节点通用或编写一个大的 if 语句以包含所有具有 onMouseEntered 事件的目标? ?

标签: javafx drag-and-drop


【解决方案1】:

我们可以把它变成一个两步(舞蹈)过程,让它变得易于管理
可管理的部分涉及将目标文本字段减少到 10 行乘 8 列
这意味着每个骰子只需要 80 次 6 行代码,总共 6720 行代码。不是很好,但它可以复制并粘贴你的心
哦,在我们狂野代码的顶部,您会看到没有价值的悬停方法
它的工作原理是按住鼠标按钮并在目标上释放
我们在可以使用 onMouseClicked 的目标区域中使用了 onMouseReleased

     @FXML
 private void onHover(){
     t4.setText(s4.getText());
 }

String move;// needs to be global
@Override
public void initialize(URL url, ResourceBundle rb) {

    s6.setOnMouseClicked((MouseEvent e)->{
      move = s6.getText();
      //s6.setVisible(false);
    });

    t1.setOnMouseReleased((MouseEvent event)->{
        if(s6.isVisible()){
        t1.setText(move);
        s6.setVisible(false);
        }
    });

    t2.setOnMouseReleased((MouseEvent e)->{
        if(s6.isVisible()){
        t2.setText(move);
        s6.setVisible(false);
        }
    });

快乐的复制和粘贴哈哈

【讨论】:

  • 感谢您的悬停 我们不确定 6720 复制和粘贴是否可行?即使它的代码行数比听众少有人必须知道用更少的代码行来管理概念的更好方法我们考虑过输入字母,当您失去焦点时,骰子(或源)被设置为不可见
【解决方案2】:

原始问题涉及使用鼠标拖放来模仿手动播放 Toss Word。
这种拖放方法效果不佳,所以这是新方法
该游戏是 Krack Games 抄写日期为 1948 年的产品,由 Adie E. Giessow 编写。
Toss Word 有 14 个骰子,骰子上的字母如下。

d1 = "GHDCEI"; d2 = "IKLHIG"; d3 = "TARSMV"; d4 = "艾尤奥"; d5 = "SABODY";
d6 = "BACEFD"; d7 = "MNKLIT"; d8 = "LMONIP"; d9 = "IEOHRF"; d10 = "MEORSN";
d11 = "EAXWYZ"; d12 = "SEAUWT"; d13 = "未射击"; d14 = "PROSTQ";

扔字规则
玩家轮流滚动字母骰子并从产生的字母中形成单词。单词必须至少有 3 个字母且没有专有名称。构成单词的每个字母都得一分。奖励:使用所有 14 个字母计为 25,而不是 14。奖励:单词“GAME”计为 50 分。

游戏设计
我们使用 TextFields 来表示骰子和目标棋盘
我们使用最少的字符来命名这些源 (s1) 和目标 (t1)
我们使用 On Mouse Clicked 事件来模拟将 Dice 字母放在目标棋盘上
然后我们使用 On Mouse Pressed Event 来允许移除 Dice 字母以放置在新位置

一旦游戏开始,我们使用布尔 PLAY = false 来禁止掷骰子
为了模拟掷骰子,我们使用了一个随机数生成器和一个单线 lambda
为了选择骰子,我们在 initialize(URL url, ResourceBundle rb)
中放置一个 lambda 表达式 这似乎让 Dice 选择过程充当了侦听器
Target Playing Board 设计的最大缺点是每个 TextField 需要 117 行代码
我们将目标棋盘减少到 10 行乘 8 列,这样棋盘上的每个 TextField 大约有 9360 行非常冗余的代码

如果有人对目标棋盘有更好的布局设计 欢迎评论!


使用了一个非常简洁的 CSS 样式声明,不是我的创作,而是在 SO
它可以防止在应用颜色样式时丢失 TextField 周围的边界
这里是 t2.setStyle("-fx-control-inner-background:lightblue")
我们将发布随机数生成器的代码 sn-p 和骰子的选择
我们将发布一个 Playing Board 交互的完整代码

掷骰子

 @FXML
 private void onRandom() throws NoSuchFieldException{
    //new Random().ints(7, 1, 7).forEach(System.out::println);
    makeEnabled();
    if(PLAY == true){
        btnOK.requestFocus();
        return;
    }
    makeVisible();
    new Random().ints(1, 1, 7).forEach(ints -> {
    int V = ints;
    String d1 = "GHDCEI";
    String S1 = String.valueOf(d1.charAt(V-1));
    s1.setText(S1);
    });<br>

选择骰子

    @Override
public void initialize(URL url, ResourceBundle rb) {

    s1.setOnMouseClicked((MouseEvent )->{
    move = s1.getText();
    s1.setVisible(false);
    PLAY = true;
    });
    s2.setOnMouseClicked((MouseEvent )->{
    move = s2.getText();
    s2.setVisible(false);
    PLAY = true;
    });<br>

在棋盘上放置和移除字母

    @FXML
private void onMC2(){
if(PLAY == false){
    t2.setStyle("-fx-control-inner-background:red");
    return;
}
t2.setText(move);
move = "";
btnOK.requestFocus();
if(t2.getText().isEmpty()){
    t2.setStyle("-fx-control-inner-background:white");
}else{;
    t2.setStyle("-fx-control-inner-background:lightblue");
}
// Code above error traps and places dice on Play Field
// Code below removes the dice to permit moving to alternate target location

t2.setOnMousePressed((MouseEvent event) -> { 
    if(t2.getText().equals(s1.getText())){
        if(!s1.isVisible()){
        s1.setVisible(true);
        t2.setText("");
        return;
        }
    }
    if(t2.getText().equals(s2.getText())){
        if(!s2.isVisible()){
        s2.setVisible(true);
        t2.setText("");
        return;
        }
    }
    if(t2.getText().equals(s3.getText())){
        if(!s3.isVisible()){
        s3.setVisible(true);
        t2.setText("");
        return;
        }
    }
    if(t2.getText().equals(s4.getText())){
        if(!s4.isVisible()){
        s4.setVisible(true);
        t2.setText("");
         return;
        }
    }
    if(t2.getText().equals(s5.getText())){
        if(!s5.isVisible()){
        s5.setVisible(true);
        t2.setText("");
        return; 
        }
    }
    if(t2.getText().equals(s6.getText())){
        if(!s6.isVisible()){
        s6.setVisible(true);
        t2.setText("");
        return;
        }
    }
    if(t2.getText().equals(s7.getText())){
        if(!s7.isVisible()){
        s7.setVisible(true);
        t2.setText("");
        return;
        }
    }
    if(t2.getText().equals(s8.getText())){
        if(!s8.isVisible()){
        s8.setVisible(true);
        t2.setText("");
        return;
        }            
    }
    if(t2.getText().equals(s9.getText())){
        if(!s9.isVisible()){
        s9.setVisible(true);
        t2.setText("");
        return;
        }  
    }
    if(t2.getText().equals(s10.getText())){
        if(!s10.isVisible()){
        s10.setVisible(true);
        t2.setText("");
        return;
        }
    }
    if(t2.getText().equals(s11.getText())){
        if(!s11.isVisible()){
        s11.setVisible(true);
        t2.setText("");
        return;
        } 
    }
    if(t2.getText().equals(s12.getText())){
        if(!s12.isVisible()){
        s12.setVisible(true);
        t2.setText("");
        return;
        }
    }
    if(t2.getText().equals(s13.getText())){
        if(!s13.isVisible()){
        s13.setVisible(true);
        t2.setText("");
        return;
        }
    }
    if(t2.getText().equals(s14.getText())){
        if(!s14.isVisible()){
        s14.setVisible(true);
        t2.setText("");
        return;
        }   
    }
});
}<br>

有一次,我们正在考虑使用一种过程来从掷骰子的结果中生成可能的单词。这是从掷骰子生成搜索组合的代码。 然后对带有流的字典运行
我们没有在游戏中加入它,它似乎破坏了游戏的想法
这是要思考的

构建搜索词的代码

Private Void buildSearchWords(){
   String W = "ILRYADIIEMASHT".toLowerCase();
   int L = W.length();
   ArrayList<String> rearange = new ArrayList<>();
   for(int i = 1; i <= L; i++){

   String firstLetter = W.substring(0, i); 
   String endLetter = W.substring(L - (L-i), L);
   String endLetterNew = W.substring(L-i);

   StringBuilder sb = new StringBuilder(W);
   sb.replace(0, i, endLetterNew);
   sb.replace(L-i, L, firstLetter);

   rearange.add(sb.toString());

   }
    for(int X = 0; X < rearange.size();X++){
        String A = rearange.get(X);
        txaInput.appendText(A);
        txaInput.appendText(" ");
    }  

与字典比较的代码

        List<String> dictionary = Arrays.asList(dictionaryArray);
    ArrayList<String> list = new ArrayList<>();

    int W = txtMonitor.getText().length();

    String newFirstLetter = txtMonitor.getText().substring(0, 1).toLowerCase();

    String newEndLetter = txtMonitor.getText().substring(W - 2, W);
    }

    dictionary.stream().filter(s -> s.startsWith(searchString)
            || s.startsWith(nF, 0)
            && s.length() > 1 && s.length() <= W+3 
            && s.endsWith(nE))
            .forEach(list :: add);

【讨论】:

  • 哇,它甚至还有编辑功能,嗯,我喜欢。谈论一个 1948 年的老歌。把它变成一个数字游戏似乎几乎是不敬的哈哈 从来没有想过把 OnMousePressed 放在 OnMouseClicked 里面 我喜欢它伟大的工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-11
  • 1970-01-01
  • 1970-01-01
  • 2016-03-10
  • 2011-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多