我开发了一个使用neo4j创建Ontology的软件。构建本体之后,我开始将200万行的数据集映射到它,这需要花费大约20分钟才能完成。因此,我希望添加一个显示流程执行的JFrame。下面的代码在开始时创建JFrame,然后它开始映射数据集。但是,我可以在执行期间看到JFrame,但是在映射完成后它的组件出现在JFrame中。我已经读过,问题可能是由于缺少围绕代码的线程。任何人都可以帮我解决这个问题吗?
void createGraphDataset(String [][] choices , final ArrayList<String[]> DatabaseFile, GraphDatabaseService BORO_DB){
JFrame converterFrame = new JFrame();
converterFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
converterFrame.setBounds(100, 100, 650, 288);
JPanel contentPane = new JPanel();
contentPane.setLayout(null);
contentPane.setVisible(true);
converterFrame.getContentPane().add(contentPane);
JPanel panelNeo1 = new JPanel();
panelNeo1.setBounds(6, 6, 638, 254);
panelNeo1.setVisible(true);
contentPane.add(panelNeo1);
panelNeo1.setLayout(null);
JLabel labelNeo1 = new JLabel("CSV BORO Converter");
labelNeo1.setBounds(16, 19, 260, 37);
panelNeo1.add(labelNeo1);
labelNeo1.setVisible(true);
JPanel panelNeo2 = new JPanel();
panelNeo2.setBounds(16, 60, 605, 167);
panelNeo1.add(panelNeo2);
panelNeo2.setLayout(null);
panelNeo2.setVisible(true);
/*
JProgressBar progressBar = new JProgressBar();
progressBar.setBounds(27, 89, 547, 20);
panelNeo2.add(progressBar);
panelNeo2.setVisible(true);
*/
JLabel labelNeo2 = new JLabel(" Processing: Number of row");
labelNeo2.setOpaque(true);
labelNeo2.setBounds(28, 36, 184, 20);
panelNeo2.add(labelNeo2);
labelNeo2.setVisible(true);
JLabel labelNeo3 = new JLabel("");
labelNeo3.setBounds(212, 36, 76, 20);
panelNeo2.add(labelNeo3);
labelNeo3.setVisible(true);
JLabel labelNeo4 = new JLabel();
labelNeo4.setText(String.valueOf(DatabaseFile.size()));
labelNeo4.setBounds(311, 36, 70, 20);
panelNeo2.add(labelNeo4);
labelNeo4.setVisible(true);
JLabel labelNeo6 = new JLabel("of");
labelNeo6.setBounds(288, 36, 23, 20);
panelNeo2.add(labelNeo6);
labelNeo6.setVisible(true);
converterFrame.setVisible(true);
TopNode= new Node [DatabaseFile.get(0).length];
//Create TopNodes
Transaction tx0 = BORO_DB.beginTx();
try{
for(int u =0; u<DatabaseFile.get(0).length;u++){
TopNode[u]=BORO_DB.createNode();
TopNode[u].setProperty("name", choices[u][0]);
}
tx0.success();
}
finally{
tx0.finish();
}
//Create the database
for(int i =0; i<DatabaseFile.size();i++){
Transaction tx2 = BORO_DB.beginTx();
try
{
// Nodes for each row
Node []graphNode= new Node [DatabaseFile.get(i).length];
// Relationships for each row ingoing
Relationship [] graphRelOn = new Relationship [DatabaseFile.get(i).length-1];
// Relationships for each row outgoing
Relationship [] graphRelOut = new Relationship [DatabaseFile.get(i).length-1];
//Relationship to TopNode ingoing
Relationship TopNodeRelIn[]=new Relationship [DatabaseFile.get(i).length];
//Creates Nodes for row and relationship to TopNode
for(int j=0; j<DatabaseFile.get(i).length;j++){
//Stores Database values
String []ValuesRow =DatabaseFile.get(i);
//Creates nodes for 1 row
graphNode[j] = BORO_DB.createNode();
graphNode[j].setProperty("name", ValuesRow[j]);
//From row to TopNode Relationship (enter)
TopNodeRelIn[j]=graphNode[j].createRelationshipTo(TopNode[j], RelTypes.typeInstances);
TopNodeRelIn[j].setProperty("relationship-type", "typeInstances");
}
//Creates Relationships
for(int k=0; k<(DatabaseFile.get(i).length)-1;k++){
//Between same elements of the same row (left to right)
graphRelOn[k]=graphNode[k].createRelationshipTo(graphNode[k+1], RelTypes.relatesTo);
graphRelOn[k].setProperty("relationship-type", "relatesTo");
//Between same elements of the same row (right to left)
graphRelOut[k]=graphNode[(DatabaseFile.get(i).length)-1].createRelationshipTo(graphNode[(DatabaseFile.get(i).length)-(2+k)], RelTypes.relatesTo);
graphRelOut[k].setProperty("relationship-type", "relatesTo");
}
tx2.success();
}
finally
{
tx2.finish();
}
}
}
答案 0 :(得分:2)
您说得对,您的问题与您的操作阻止负责绘制组件的线程的问题有关。但是,解释多线程编程的所有方面超出了单一答案的范围。
作为一种解决方法,您可以延迟计算。
// setup the GUI
frame.setVisible(true);
EventQueue.invokeLater(new Runnable() {
public void run()
{
doYourHavyComputation();
}
});
这样,您的计算仍然在同一个线程中运行并阻止UI,但是在以后绘制初始帧内容时。
如果你想做真正的背景计算,你必须学习一个或多个关于多线程的教程,以了解所有的复杂情况,然后尝试一下,如果你有更具体的问题,请回来。
答案 1 :(得分:0)
我已经读过,问题可能是由于缺少一个线程 围绕代码
将是一个合适的假设。 Swing是一个单线程环境,这意味着,UI的所有交互和更新都需要在Event Dispatching Thread的上下文中进行。同样在阻止该线程的操作或操作中将阻止EDT处理(除其他事项外)绘制请求。
虽然有许多可能的解决方案,但最适合您需求的可能是SwingWorker
。
这允许您在后台线程中运行冗长的操作,但是有许多方法可以将这些操作的重新同步重新同步到EDT。
查看Concurrency in Swing了解详情。
您如何使用它将取决于您的需求...
例如,您可以简单地“发布”您正在处理的当前行...
public class Generator<Node , Integer> {
protected void process(List<Integer> rows) {
// Back in the EDT
int lastRow = rows.get(rows.size() - 1); // Only interested in the last one...
// Update the UI...
}
protected Node doInBackground() throws Exception {
Node topNode = new Node [DatabaseFile.get(0).length];
/*...*/
publish(rowNumber);
/*...*/
return topNode;
}
public void done() {
// Back in the EDT
try {
Node topNode = get(); // Get the result of the calculation...
} catch (Exception exp) {
exp.printStackTrace();
}
}
}
或者您可以利用SwingWorker
的属性更改支持,并在构建的setProgress
方法中使用它。
请参阅...
举个例子。
这些将确保您完整地处理您的计算,UI仍然可以响应您的更改