65.9K
CodeProject 正在变化。 阅读更多。
Home

一个 TCL-TK 表单生成器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2019年9月30日

CPOL

3分钟阅读

viewsIcon

9651

downloadIcon

216

一个 Tcl-Tk 表单生成器,可以单独使用,也可以为那些活动可能很复杂的语言提供快速的表单生成。

引言

本文介绍了一个用 Tcl - Tk 开发的表单生成器[1] (TK FormGen),用于创建和管理表单,从简单的消息框到具有文本字段、组合框、单选按钮等等的相对复杂的表单。TK FormGen 可以被 TCL 应用程序使用,或者被其他语言调用,特别是那些没有原生 GUI 的语言;这里,与其对产品进行详尽的介绍[2],不如说明它如何被其他语言使用。

使用程序

表单生成器由脚本fGen.tclfGenProc.tcl组成,前者包含生成表单的过程,后者包含一些过程;后者会被fGen.tcl自动包含。
表单生成器可以被调用

  • 通过 Tcl 脚本
    proc cBack {data} {
    	foreach id [dict keys $data] {puts "$id\t : [dict get $data $id]"}
    	exit
    }
    append src [file dirname [file normalize [info script ]]] "/fGen.tcl"
    source $src
    set ask "Title,Form generalities;Ground,silver;"
    append ask "CMB,Theme,,,|alt|clam|classic|default|vista|winnative|xpnative;"
    append ask "CMB,Ground,,,|cyan|gray|magenta|olive|silver|teal;"
    append ask "CMB,Form,Form type,,|T:Texts|B:Buttons|C:Combo boxes|F:Files 
           and folders|S:Scales and combos;"
    append ask "Default,Theme:clam,Ground:teal;"
    formGen[list $ask cBack]
  • 直接从命令行,例如tclsh fgen.tcl "T,name,User name;P,psw,Enter password" data.json
  • 通过另一种语言

与其他语言一起使用表单生成器

这些示例处理一个表单(见上图),该表单可用于测试小部件,也可用于探索不同的表单背景和主题。

当表单关闭时,数据以 Json 格式发送到标准输出,以便转换为宿主语言的内部变量;以下是文件params.txt中包含的用于创建表单的列表

CMB,Theme;# themes are set at the beginning with the available themes;
Labels,Right, :;
Comment,Hexadecimal color value must have the form #RRGGBB;
CMT,Ground,,,|cyan|gray|magenta|olive|silver|teal|#C0D0E0;
CMB,Form,
Form examples,,|Texts|Buttons|Combo boxes|Files and folders|Scales and Check box;
T,try,Try this,400;
Default,Theme:clam,Ground:teal;
Validate,Ground is ^#[0-9a-fA-F]{6}$,Not valid color;
Default,try:C#2CThis is a form for test some widgets\nCondor Informatique - Turin#3b
CMB#2CGround#2C#2C#2C|cyan|gray|magenta|olive|silver|teal|#C0D0E0;

在使用 TK FormGen 测试的所有语言中,表单都是通过外部命令执行 TCL 解释器生成的,数据从标准输出读取并转换为内部变量。
发送的命令是:tclsh fGen.tcl params.txt handler.tcl::tryForm handler.tcl::handle,其中tclsh是 Tcl 解释器,fGen.tcl是一个 Tcl 脚本,如果使用适当的参数调用,它会生成一个表单。handler.tcl包含一个过程handle,用于管理事件,特别是组合框 Form 的事件Start和事件Select。当表单关闭时,会调用过程tryForm,它会从字段try中获取数据并生成一个新表单。

namespace eval handler {
	variable examplesMap [dict create \
			"Texts" "Text,Text;P,psw,Password,,Almost 6 characters;T,
             Mail,E mail,18;N,Number;IN,Integer,Integer Number;\
		     DN,DecNumber,Decimal Number;A,textArea,Text area,5;;
             Default,Mail:ross@lib.it,Integer:7,Number:-11,DecNumber:3.1415;" \
			"Scales and Check box" "CMB,greeck,Greek letters,,
             A:Alfa|Beta|G:Gamma|Delta;CMT,spinBox,Combo and text,,
             A:Alfa|Delta|G:Gamma|Omega|T:Tau;\
				Scale,Scale2,Scale 2,222,1 -1;QS,Urgency,,,
                White|Green|Yellow|Red;Default,Scale2:-0.35,Urgency:Yellow,ckBox:1; \
				Check,ckBox,Check box,,Accept news;Check,ckBox2,Check box2,,Agree;" \
			"Buttons" "P,psw,Password,18;RDB,Gender,,,M:Male|F:Female|
             U:Unspecified;B,infoButton,\u24d8,,infoPsw;After,infoButton,psw;\
				B,Start,\u270E;B,fg_Cancel,\u2718;B,fg_Reset,\u21B6;
                Default,Gender:M;Required,psw;Validate,psw is .{6#2c},Password too short;\
				RDB,Langue,,,us:img\\uss.png|fr:img\\frs.png;"\
			"Combo boxes" "CMB,greeck,Greek letters,,A:Alfa|Beta|G:Gamma|Delta;CMT,
             spinBox,Combo and text,,A:Alfa|Delta|G:Gamma|Omega|T:Tau;"\
			"Files and folders" "File,File,,40,Images:*.gif *.jpg *.png,All:*;
             Default,File:C:\\www\\condorinformatique\\nodejs\\tcl;D,
             Folder,,30;WF,wFile,Write File;"]
}
proc handle {e} {
	lassign $e event path name
	if {$event == "Start"} {
		# populate the combo Theme with themes supported 
		fg_setCombo Theme "[join [ttk::style theme names] "|"]"
	}
	if {$name == "Form" && $event == "Select"} {
		# Insert in text area a sample of form
		if {[valueOf $name] != ""} {setValue try 
           "[dict get $::handler::examplesMap [valueOf $name]]"}
	}
}
proc tryForm {data} {
	append prefix "Title,Form example of " [dict get $data "Form"] ";Ground," 
           [dict get $data "Ground"] "," [dict get $data "Theme"] ";Labels,Right, :;"
	set systemTime [clock seconds]
	append prefix "H,hField,[clock format $systemTime];" [dict get $data "try"]
	formGen [list "$prefix"]
}

下面是一个输出示例 (Ruby)。

>ruby tcltk.rb
{
  "fg_Button" => "Ok",
  "Text" => "Text",
  "psw" => "Lafayette77",
  "Mail" => "ross@lib.it",
  "Number" => -11,
  "Integer" => 17,
  "DecNumber" => 3.1415,
  "textArea" => "big\ttext\n\n"
}
Sum: 9.141500
>Exit code: 0

与语言一起使用

C++

在 C++ 11 中使用 FGen 最为费力;选择 C++ 而不是 C 是因为它支持正则表达式和map结构。

我没有使用 Json 库,以避免包含第三方库,另一方面,我只需要读取一个简单的键值结构,所以我更喜欢使用正则表达式来提取键值对并将它们插入到map中(函数json2Map)。

// C++ 11
#include <bits stdc="">
using namespace std;
// function to find all the matches
map<string, string=""> <code>json2Map</code>(string jsonData) {
    map<string, string=""> dataMap;
    string regExspr("\\\"(\\w+)\\\":\\s*(\\\"([^\"]*)\\\"|(([+-]?\\d*)(\\.\\d+)?))");
    regex re(regExspr);
    for (sregex_iterator it = sregex_iterator
        (jsonData.begin(), jsonData.end(), re);it != sregex_iterator(); it++) {
            smatch match;
            match = *it;
            int indexValue = 3;
            if (match.str(3) == "") indexValue = 2;
            cout << match.str(1) << "\t" << match.str(indexValue) << endl;
            dataMap[match.str(1)] =  match.str(indexValue);
    }
    return dataMap;
}
int main( int numberArgs, char* argsList[] ) {
    vector<string> params{ "fGen.tcl","T,t1;N,n1", "", "" };
    int commandLength = 40; // roughly default + fixed (i.e. tclsh ... >j.json)
    for (int i=1; i<numberargs; i=""> j.json", params[0].c_str(), 
         params[1].c_str(),params[2].c_str(),params[3].c_str());
    int status = system(tcl);
    ifstream jsonFile("j.json");
    string jsonData {istreambuf_iterator<char>(jsonFile), istreambuf_iterator<char>()};
    cout << jsonData << endl;
    map<string, string=""> dataMap = json2Map(jsonData);
    if (dataMap.count("Integer") > 0) {
        cout << "Sum: " << (atof(dataMap["Integer"].c_str()) + 
        atof(dataMap["Number"].c_str()) + atof(dataMap["DecNumber"].c_str())) << endl;
    }
	return 0;
}
节点
const args = process.argv.slice(2)
const {exec} = require('child_process');
var command = 'tclsh ' + args[0] + ' "' + args[1] + '" ' + args[2] + ' "' + args[3]
const tcl = exec(command, function (error, stdout, stderr) {
	if (error) {    
		console.error(`exec error: ${error}`);
		return;
	}
	console.log('Child Process STDOUT: '+stdout); 
});
let jsonData = '';
tcl.stdout.on('data', (chunk) => {
  jsonData += chunk.toString();
});
tcl.on('exit', () => {
	console.log(jsonData);
	var data = JSON.parse(jsonData)	// the data becomes a JavaScript object 
	if ("Integer" in data) {
			console.log("Sum " + (data.Integer + data.Number + data.DecNumber))
	}
});
Python
import os
import subprocess
import json
def main():
    pass
os.chdir("C:\\Sviluppo\\fGenTk\\")
p = subprocess.Popen("tclsh fGen.tcl params.txt handler.tcl::tryForm handler.tcl::handle", 
                      shell=True, stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
data = json.loads(stdout.decode('utf-8'))
print(data)
if 'Integer' in data:
   print ("Sum: {}".format(data['Integer'] + data['Number'] + data['DecNumber']))
if __name__ == '__main__':
    main()
R
library("rjson")
setwd("C:\\Sviluppo\\fGenTk")
parameters <- c("fGen.tcl", "params.txt", "handler.tcl::tryForm", "handler.tcl::handle")
json <- system2("tclsh",parameters,stdout=TRUE)
tmp <- tempfile()
cat(json,file = tmp)
data <- fromJSON(readLines(tmp))
data$fg_Button
if ("Integer" %in% names(data)) 
	cat("Sum:",data$Integer + data$Number + data$DecNumber,"\n")
Ruby

Ruby 可能是使用 TK Fgen 最简单的,只需两条指令,我们就可以得到formdata

require 'json'
require 'FileUtils'
FileUtils.cd('c:/Sviluppo/fGenTk')
output = `tclsh fGen.tcl params.txt handler.tcl::tryForm handler.tcl::handle`
data = JSON.parse(output) if output != ""
puts JSON.pretty_generate(data).gsub(":", " =>")
if data.has_key?("Integer") then
	puts sprintf("Sum: %f",data['Integer'] + data['Number'] + data['DecNumber'])
end

注意

  1. ^ 这是我 网站上可以找到的一些表单生成器之一(适用于 Autoit、Powershell、B4A、B4J 和 JavaScript)。
    此外,CodeProject 上还有一些文章
    1. JavaScript 表单生成器
    2. Android 表单生成器
    3. 一个 PowerShell 表单生成器 [提示/技巧]
  2. ^ 软件包和文档可以在这里下载。

历史

  • 2019 年 9 月 30 日:初始版本
© . All rights reserved.