Blockly中串联自定义块仅首个生成C++代码问题排查
问题
我在Google Blockly中自定义了可生成C++代码的块,单独使用时功能正常,但将这些块串联使用时,仅首个块能生成代码,后续连接的块完全无法生成代码。
相关代码如下:
const toolbox = { ... } const cppGenerator = new Blockly.Generator('cppGenerator'); Blockly.Blocks['start_of_file'] = { init: function() { this.appendDummyInput() .appendField("File name:") .appendField(new Blockly.FieldTextInput("main"), "filename"); this.appendDummyInput() .appendField("Description: ") .appendField(new Blockly.FieldTextInput("The main file"), "description"); this.setNextStatement(true, null); this.setColour(230); this.setTooltip(""); this.setHelpUrl(""); } }; Blockly.Blocks['include'] = { init: function() { this.appendDummyInput() .appendField("use the") .appendField(new Blockly.FieldTextInput("iostream"), "header") .appendField("header"); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setColour(230); this.setTooltip(""); this.setHelpUrl(""); } }; cppGenerator.forBlock['start_of_file'] = function(block, generator) { var filename = block.getFieldValue('filename'); if (filename.slice(-4) != ".cpp") { filename += ".cpp" } var description = block.getFieldValue('description'); console.log(block) return `// ${filename} // ${description}`; } cppGenerator.forBlock['include'] = function(block, generator) { var header = block.getFieldValue('header'); return `#include <${header}>` } const workspace = Blockly.inject('blocklyDiv', { toolbox: toolbox }); function updateCode(event) { const code = cppGenerator.workspaceToCode(workspace); document.getElementById('textarea').value = code; } // workspace.addChangeListener(Blockly.Events.disableOrphans); workspace.addChangeListener(updateCode);
当前效果:
预期效果:
原因分析
Blockly生成器默认只会处理当前块的代码,不会自动遍历后续连接的块。如果你的块设置了setNextStatement(true),就需要在生成器函数中主动调用generator.statementToCode(block, 'NEXT')来获取后续块的代码,并将其与当前块的代码拼接。
解决方案
修改两个块的生成器函数,添加获取后续语句的逻辑:
cppGenerator.forBlock['start_of_file'] = function(block, generator) { var filename = block.getFieldValue('filename'); if (filename.slice(-4) != ".cpp") { filename += ".cpp" } var description = block.getFieldValue('description'); // 获取后续块的代码 const nextCode = generator.statementToCode(block, 'NEXT'); return `// ${filename} // ${description} ${nextCode}`; } cppGenerator.forBlock['include'] = function(block, generator) { var header = block.getFieldValue('header'); // 获取后续块的代码 const nextCode = generator.statementToCode(block, 'NEXT'); return `#include <${header}> ${nextCode}`; }
说明
generator.statementToCode(block, 'NEXT')会递归处理当前块之后连接的所有块,生成对应的代码- 将后续代码与当前块代码拼接时,注意添加换行符保证代码格式正确
- 修改后,串联的块就能依次生成对应的C++代码
内容的提问来源于stack exchange,提问作者FortCraftCoder
相关产品推荐
相关产品推荐

