我应该在EDT中创建摆动元素吗?
我在编辑非线程安全的图形元素时遇到了并发性问题,但我正在创建它们,但尚未显示出来,如果它们太多或需要花费一些时间来分配,这将冻结GUI,但不会。是吗?
这是我使用EDT显示但不创建GUI结构的示例:
public class Launcher {
private final SwingWorker worker;
private final JFrame frame;
private final JLabel label;
private final JProgressBar progressBar;
public Launcher() {
// init user interface
frame = new JFrame();
JPanel panel = new JPanel(new BorderLayout());
label = new JLabel("Launching...", SwingConstants.CENTER);
progressBar = new JProgressBar(0, 100);
progressBar.setIndeterminate(true);
panel.add(label, BorderLayout.CENTER);
panel.add(progressBar, BorderLayout.PAGE_END);
initUI(panel);
worker = new LauncherWorker(this);
worker.addPropertyChangeListener((PropertyChangeListener)this);
}
private void initUI(final Component panel) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
DirectaChatLauncher.this.initUI(panel);
} //run()
});
return;
}
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(panel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
int progress = (Integer) evt.getNewValue();
progressBar.setValue(progress);
}
}
private void setProgression(final String msg) {
label.setText(msg);
}
class LauncherWorker extends SwingWorker<Boolean, String> {
private final Launcher LAUNCHER;
public LauncherWorker(Launcher launcher) {
super();
LAUNCHER = launcher;
}
@Override
protected Boolean doInBackground() throws Exception {
setProgress(0);
publish("Started");
...
setProgress(100);
publish("Launched");
Thread.sleep(1000);
return Boolean.TRUE;
}
@Override
protected void process(List<String> chunks) {
LAUNCHER.setProgression(chunks.get(0));
}
@Override
public void done() {
LAUNCHER.done();
}
}
}
因为元素还没有显示好吗?还是我应该全部搬进去initUI()
?
在Swing
可分离模型体系结构中
,视图组件侦听其模型。因为视图可以任意响应模型更新生成的事件,所以相应的模型 也 必须在EDT上进行更新。您可以通过以下两种基本方法之一来减少延迟:
使用EventQueue.invokeLater()
从一个单独的线程,如图所示这里。
使用SwingWorker
以获得额外的好处列举在这里。
由于大小,您一定要在后台加载文件,以避免阻塞事件分发线程;SwingWorker是一个常见的选择。与其使用a Document,不如考虑更新aTableModel并在a的行中显示文本行JTable。这具有几个优点:
结果将立即开始显示,并且可以减少感知到的延迟。
您可以在读取输入时对其进行解析,以创建任意列结构。
您可以利用排序和过滤的功能JTable,为例子。
您可以用来TablePopupEditor将重点放在一行上。
附录:以下示例DefaultTableModel为方便起见。为了降低开销,扩展AbstractTableModel和管理List
码:
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
/**
* @see https://stackoverflow.com/a/25526869/230513
*/
public class DisplayLog {
private static final String NAME = "/var/log/install.log";
private static class LogWorker extends SwingWorker<TableModel, String> {
private final File file;
private final DefaultTableModel model;
private LogWorker(File file, DefaultTableModel model) {
this.file = file;
this.model = model;
model.setColumnIdentifiers(new Object[]{file.getAbsolutePath()});
}
@Override
protected TableModel doInBackground() throws Exception {
BufferedReader br = new BufferedReader(new FileReader(file));
String s;
while ((s = br.readLine()) != null) {
publish(s);
}
return model;
}
@Override
protected void process(List<String> chunks) {
for (String s : chunks) {
model.addRow(new Object[]{s});
}
}
}
private void display() {
JFrame f = new JFrame("DisplayLog");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultTableModel model = new DefaultTableModel();
JTable table = new JTable(model);
JProgressBar jpb = new JProgressBar();
f.add(jpb, BorderLayout.NORTH);
f.add(new JScrollPane(table));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
LogWorker lw = new LogWorker(new File(NAME), model);
lw.addPropertyChangeListener((PropertyChangeEvent e) -> {
SwingWorker.StateValue s = (SwingWorker.StateValue) e.getNewValue();
jpb.setIndeterminate(s.equals(SwingWorker.StateValue.STARTED));
});
lw.execute();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
new DisplayLog().display();
});
}
}
我已经用ImageView和TextView制作了抽屉菜单,它可以run.However,当我想用两个ImageView和一个TextView创建抽屉菜单时,它会用我的第二个ImageView显示错误(“尝试调用虚拟方法”)(我代码中的变量名称是“img”) 我的代码如下: 这是我的日志: 09-16 22:25:38.458:E/AndroidRuntime(14966):致命例外:主 09-1
问题内容: 是否存在有关嵌套HTML 和HTML元素的最佳实践? 经典方式: 要么 问题答案: 从w3开始:标签本身可以位于相关控件之前,之后或周围。 要么 要么 请注意,当表格用于布局时,不能使用第三种技术,标签位于一个单元格中,而其关联的表单字段位于另一个单元格中。 任一有效。我喜欢使用第一个或第二个示例,因为它可以为您提供更多的样式控制。
问题内容: 如何在 jQuery中 创建元素? 问题答案: 您可以使用(在父级的最后一个位置添加)或(在父级的第一个位置添加): 或者,您可以使用或
根据一个字符串创建一个元素(不附加到 document )。 如果给定的字符串包含多个元素,则只返回第一个元素。 使用 document.createElement() 来创建一个新的元素。 将它的 innerHTML 设置为作为参数提供的字符串。 使用 ParentNode.firstElementChild 来返回字符串的元素版本。 const createElement = str => {
问题内容: 我有一个可以为其创建一个(或多个)实例的实例。我正在使用Servlet环境,并且已经将一个EntityManagerFactory连接到Servlet(通过Servlet上下文),该Servlet在Servlet的生命周期中(因此,对于所有用户)都共享。 我可以执行以下操作之一: 在我的Servlet的生存期内创建一个EntityManager(例如,在所有用户之间共享) 为每个用户创
问题内容: 我想实现一个JTreeTable。我在Java官方网站上看到了该示例。我是Java的初学者,我无法理解该示例。我将树节点和子名称作为字符串。我该如何实施? 问题答案: 有(只有我尝试过的产品) 自由 swingx NetBeans ,在此处说明 Aephyr的出色解决方法 这里的简单代码示例 非自由 积德网格