java - 为什么打印某些东西(在 Java 中)会改变是否显示 JFrame 的连续实例?
问题描述
我试图基本上 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");
}
的代码displayAutomaton
如下:
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 中,一个接一个,每个新窗口仅在我关闭前一个窗口后打开,这正是我想要的 - 但我显然不想每次都打印“this works”,所以我试图删除这个简单的指令。但是,然后代码不再起作用 - 这样,只显示第一张图像,在我关闭它之后,什么也没有发生。
我尝试简单地在此处结束该行,断言 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()
。
解决方案
推荐阅读
- java - 这是对 java ClassGraph api 的有效使用吗?
- php - Codeigniter 网站在 Google Virtual Instant Live Server 上显示错误 404
- amazon-web-services - AWS 服务是区域性的还是全球性的有什么区别?
- javascript - 如何修复 jquery 帖子中的 html 错误?
- r - 获取多个分组依据的最高值
- python - 使用curve_fit对噪声数据进行高斯拟合
- java - 尽管进行了所有扫描,Springboot 都找不到我的自动装配 bean
- javascript - 下载图片后html2canvas字体已更改
- javascript - 在javascript中使用箭头函数返回名字和姓氏的首字母
- wmi - Prometheus 错误 - 超出上下文截止日期