问题描述
我基本上尝试 1) 创建随机 DFA 和 2) 使用 JFrame 一个接一个地显示它们。我已经研究出如何随机创建 DFA,让 GraphViz 负责将它们可视化并将它们保存在 .png 文件中,然后将它们显示在 JFrame 中。 DFA 在循环中创建,在该循环中调用函数 displayAutomaton
,该函数负责创建 .png 和显示它。
for(int i = 2; i < 10; i++) {
AutomatonConverter.displayAutomaton(createrandomDFA(i));
while(AutomatonConverter.jFrameExists) System.out.println("this works");
}
public static void displayAutomaton(Automaton A) {
// Create the automaton-dependent file name
String fileName = getAutomatonName(A);
// Convert the Automaton and save it in a .png
convertAutomaton(A,fileName);
JFrame frame = new JFrame();
// This static variable is used to determine whether the window
// has been closed,so that the next iteration in the loop can start
jFrameExists = true;
ImageIcon icon = new ImageIcon(fileName);
JLabel label = new JLabel(icon);
frame.add(label);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
jFrameExists = false;
frame.dispose();
}
});
frame.pack();
frame.setVisible(true);
}
如您所见,我在主循环中使用静态变量 jFrameExists
来推断窗口是否已关闭,因为我想连续打开自动机的不同图像。为此,我覆盖了框架的 Window-Listener。这是奇怪的部分:正如您在上面看到的,在显示自动机之后,while 循环会询问 jFrameExists
是否已设置为 false(这再次发生在窗口关闭时)。目前,所有这些都有效。每个创建的自动机都显示在不同的 JFrame 中,一个接一个,每个新窗口仅在我关闭前一个窗口后打开,这正是我想要的 - 但我显然不想每次都打印“这个作品”,所以我试图删除这个简单的指令。但是,然后代码不再工作 - 这样,只显示第一张图像,关闭它后,什么也没有发生。
我曾尝试简单地在那里结束该行,断言 true (while(AutomatonConverter.jFrameExists) assert true;
),并创建空的 void 方法放置在这里 (while(AutomatonConverter.jFrameExists) donothing();
),但没有任何工作正常 - 同样,这种方式只有第一个显示图像,并且循环似乎不会继续到下一个自动机。我就是不明白为什么。有人有什么想法吗?
编辑:这是我的代码的通用版本,希望更容易理解(忽略 convertAutomaton 和 createrandomDFA 中的代码,为了完整起见,我只是添加了它):
public class main {
static boolean jFrameExists = false;
public static void convertAutomaton(Automaton A,String fileName) {
// Creates a png of the automaton A and saves it under the fileName
GraphViz gv = new GraphViz();
gv.addln(gv.start_graph());
gv.addln("rankdir=LR;");
String startName;
String shape;
if(A instanceof DFA) {
// Create the starting node
State q0 = ((DFA) A).getQ0();
startName = "\"" + q0.getName() + "start\"";
shape = A.getF().contains(q0) ? "doublecircle" : "circle";
// Add the node itself...
gv.addln("node [shape = " + shape + "]; \"" + q0.getName() +"\";");
// ... and its corresponding entry arrow
gv.addln("node [shape = point]; " + startName + ";");
gv.addln(startName + " -> \"" + q0.getName() + "\"");
// Create all accepting nodes
for(State s : A.getF()) {
if(!((DFA) A).getQ0().equals(s)) gv.addln("node [shape = doublecircle]; \"" + s.getName() +"\";");
}
} else {
// Create all starting nodes
for(State s : ((NFA) A).getQ0()) {
startName = "\"" + s.getName() + "start\"";
shape = A.getF().contains(s) ? "doublecircle" : "circle";
// Add the node itself...
gv.addln("node [shape = " + shape + "]; \"" + s.getName() +"\";");
// ... and its corresponding entry arrow
gv.addln("node [shape = point]; " + startName + ";");
gv.addln(startName + " -> \"" + s.getName() + "\"");
}
// Create all accepting nodes
for(State s : A.getF()) {
if(!((NFA) A).getQ0().contains(s)) gv.addln("node [shape = doublecircle]; \"" + s.getName() +"\";");
}
}
gv.addln("node [shape = circle];");
// Create all transitions
ArrayList<State> reachable;
String sName,s2Name;
for(State s : A.getStates()) {
for(char c : Automaton.alphabet) {
sName = "\"" + s.getName() + "\"";
reachable = s.delta(c);
for(State s2 : reachable) {
s2Name = "\"" + s2.getName() + "\"";
gv.addln(sName + " -> " + s2Name + " [ label = \"" + c + "\" ];");
}
}
}
gv.add(gv.end_graph());
File out = new File(fileName);
gv.writeGraphToFile(gv.getGraph(gv.getDotSource(),type),out );
}
}
public static void displayAutomaton(Automaton A) {
String fileName = "automaton.png"
convertAutomaton(A,fileName);
JFrame frame = new JFrame();
jFrameExists = true;
ImageIcon icon = new ImageIcon(fileName);
JLabel label = new JLabel(icon);
frame.add(label);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
jFrameExists = false;
frame.dispose();
}
});
frame.pack();
frame.setVisible(true);
}
public static Automaton createrandomDFA(int numberOfStates) {
// Create the states
ArrayList<State> states = new ArrayList<State>();
for(int i = 0; i < length; i++) states.add(new State(Integer.toString(i)));
// Create random transitions
Random r = new Random();
State rState;
for(State s : states) for(char c : Automaton.alphabet) {
rState = states.get(r.nextInt(length));
s.addTransition(c,rState);
}
// Create random accepting states
ArrayList<State> F = new ArrayList<State>();
for(State s : states) {
if(r.nextInt(length) == length - 1) F.add(s);
}
if(F.size() == 0) F.add(states.get(r.nextInt(length)));
// Create random starting state
State q0 = states.get(r.nextInt(length));
return new DFA(states,q0,F);
}
}
public static void main(String[] args) {
for(int i = 2; i < 10; i++) {
displayAutomaton(createrandomDFA(i));
while(jFrameExists) System.out.println("waiting until the window is closed");
}
}
}
基本上就是这样。我知道不在自己的类中实现所有可视化内容并简单地关闭窗口而不是添加处理我想要的功能的按钮是很奇怪的,但从长远来看,我基本上不想可视化任何东西,这只是应该测试是否正确创建了自动机。将来我会尝试更符合编码标准的不同方法,但我仍然很想知道为什么调用 System.out.println()
会有所不同。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)