Java Swing Workers 和组合框问题
我正在使用 Swing 构建一个使用数据库的应用程序。 我有一个奇怪的问题,我不知道如何解决。
在某个面板中,我有一个组合框,我想使用数据库查询来填充记录。 完成构建包含组合框的 JPanel 后,我正在执行一个 Worker,
private void populateLists(){
GetSimpleRecordsWorker worker = new GetSimpleRecordsWorker(Tables.characters,panelLeftDetails);
worker.execute();
}
其 doInBackground
执行 SELECT 查询,并在获取结果后 - 在 Worker 的 done()
方法中 -更新面板的模型并调用面板的refreshFromModel
。
charI.setSimpleModel(simpleModel);
charI.refreshFromModel();
refreshFromModel
执行以下操作:
private void refreshFromSimpleModel(){
charSelectCombo.removeAllItems();
Pair[] pairs = simpleModel.getRecords();
for (int i=0; i<pairs.length; i++){
charSelectCombo.addItem(pairs[i]);
}
charSelectCombo.setSelectedItem(null);
}
现在,问题是,在完成refreshFromModel 后 - GUI 卡住/冻结。 我不知道为什么! 奇怪的是,在不同的框架中,我使用相同的方法 - 而且它的工作没有任何问题。
另外,如果我尝试 removeAll
而不是 removeAllItems
它可以工作,但 ComboBox 会丢失箭头并且表现得很奇怪。
我已经在调试器中获取了帧跟踪 - 像removeSourceEvent或Unsafe.park之类的东西都在那里。
GUI.GuiHandler at localhost:53547 (Suspended)
Daemon System Thread [Attach Listener] (Suspended)
Daemon System Thread [Signal Dispatcher] (Suspended)
Daemon System Thread [Finalizer] (Suspended)
Object.wait(long) line: not available [native method]
ReferenceQueue<T>.remove(long) line: not available
ReferenceQueue<T>.remove() line: not available
Finalizer$FinalizerThread.run() line: not available
Daemon System Thread [Reference Handler] (Suspended)
Object.wait(long) line: not available [native method]
Reference$Lock(Object).wait() line: 485
Reference$ReferenceHandler.run() line: not available
Thread [AWT-Shutdown] (Suspended)
Object.wait(long) line: not available [native method]
Object.wait() line: 485
AWTAutoShutdown.run() line: not available
Thread.run() line: not available
Daemon System Thread [Java2D Disposer] (Suspended)
Object.wait(long) line: not available [native method]
ReferenceQueue<T>.remove(long) line: not available
ReferenceQueue<T>.remove() line: not available
Disposer.run() line: not available
Thread.run() line: not available
Daemon Thread [AWT-Windows] (Suspended)
WToolkit.eventLoop() line: not available [native method]
WToolkit.run() line: not available
Thread.run() line: not available
Thread [AWT-EventQueue-0] (Suspended)
EventQueue.removeSourceEvents(Object, boolean) line: not available
WindowsComboBoxUI$WindowsComboBoxRenderer(Component).removeNotify() line: not available
WindowsComboBoxUI$WindowsComboBoxRenderer(Container).removeNotify() line: not available
WindowsComboBoxUI$WindowsComboBoxRenderer(JComponent).removeNotify() line: not available
CellRendererPane(Container).remove(int) line: not available
CellRendererPane(Container).remove(Component) line: not available
WindowsComboBoxUI(BasicComboBoxUI).getSizeForComponent(Component) line: not available
WindowsComboBoxUI(BasicComboBoxUI).getDisplaySize() line: not available
WindowsComboBoxUI(BasicComboBoxUI).getMinimumSize(JComponent) line: not available
AutoCompleteComboBox(JComponent).getMinimumSize() line: not available
FlowLayout.minimumLayoutSize(Container) line: not available
JPanel(Container).minimumSize() line: not available
JPanel(Container).getMinimumSize() line: not available
JPanel(JComponent).getMinimumSize() line: not available
BoxLayout.checkRequests() line: not available
BoxLayout.minimumLayoutSize(Container) line: not available
JPanel(Container).minimumSize() line: not available
JPanel(Container).getMinimumSize() line: not available
JPanel(JComponent).getMinimumSize() line: not available
BoxLayout.checkRequests() line: not available
BoxLayout.preferredLayoutSize(Container) line: not available
JPanel(Container).preferredSize() line: not available
JPanel(Container).getPreferredSize() line: not available
JPanel(JComponent).getPreferredSize() line: not available
BorderLayout.layoutContainer(Container) line: not available
JPanel(Container).layout() line: not available
JPanel(Container).doLayout() line: not available
JPanel(Container).validateTree() line: not available
JPanel(Container).validateTree() line: not available
JPanel(Container).validateTree() line: not available
JLayeredPane(Container).validateTree() line: not available
JRootPane(Container).validateTree() line: not available
JRootPane(Container).validate() line: not available
RepaintManager.validateInvalidComponents() line: not available
SystemEventQueueUtilities$ComponentWorkRequest.run() line: not available
InvocationEvent.dispatch() line: not available
EventQueue.dispatchEvent(AWTEvent) line: not available
EventDispatchThread.pumpOneEventForFilters(int) line: not available
EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: not available
EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: not available
EventDispatchThread.pumpEvents(int, Conditional) line: not available
EventDispatchThread.pumpEvents(Conditional) line: not available
EventDispatchThread.run() line: not available
Thread [DestroyJavaVM] (Suspended)
Daemon System Thread [D3D Screen Updater] (Suspended)
Object.wait(long) line: not available [native method]
D3DScreenUpdateManager.run() line: not available
Thread.run() line: not available
Daemon System Thread [TimerQueue] (Suspended)
Object.wait(long) line: not available [native method]
TimerQueue.run() line: not available
Thread.run() line: not available
Thread [Thread-3] (Suspended)
Thread.sleep(long) line: not available [native method]
JDCConnectionPool$ConnectionReaper.run() line: 93
Daemon Thread [SwingWorker-pool-1-thread-1] (Suspended)
Unsafe.park(boolean, long) line: not available [native method]
LockSupport.park(Object) line: not available
AbstractQueuedSynchronizer$ConditionObject.await() line: not available
LinkedBlockingQueue<E>.take() line: not available
ThreadPoolExecutor.getTask() line: not available
ThreadPoolExecutor$Worker.run() line: not available
Thread.run() line: not available
非常感谢。
I'm using Swing to build an application that uses a database.
I have a weird problem that I don't understand how to solve.
In a certain panel, I have a comboBox which I want to populate with records using DB query.
after finishing constructing the JPanel which hold the comboBox, I'm executing a Worker
private void populateLists(){
GetSimpleRecordsWorker worker = new GetSimpleRecordsWorker(Tables.characters,panelLeftDetails);
worker.execute();
}
Its doInBackground
does a SELECT query and after getting the result - in the Worker's done()
methods - updates the panel's model and calls the panel's refreshFromModel
.
charI.setSimpleModel(simpleModel);
charI.refreshFromModel();
refreshFromModel
does the following :
private void refreshFromSimpleModel(){
charSelectCombo.removeAllItems();
Pair[] pairs = simpleModel.getRecords();
for (int i=0; i<pairs.length; i++){
charSelectCombo.addItem(pairs[i]);
}
charSelectCombo.setSelectedItem(null);
}
Now, the problem is, after it finish refreshFromModel - the GUI stuck/freeze.
I HAVE NO IDEA WHY!
Weird is, in a different frame, I use the same methodology - and it works with no problems.
Also, if I try removeAll
instead of removeAllItems
it works but the ComboBox loses its arrow and acts weird.
I've taken the frame trace in the debugger - things like removeSourceEvent or Unsafe.park are there.
GUI.GuiHandler at localhost:53547 (Suspended)
Daemon System Thread [Attach Listener] (Suspended)
Daemon System Thread [Signal Dispatcher] (Suspended)
Daemon System Thread [Finalizer] (Suspended)
Object.wait(long) line: not available [native method]
ReferenceQueue<T>.remove(long) line: not available
ReferenceQueue<T>.remove() line: not available
Finalizer$FinalizerThread.run() line: not available
Daemon System Thread [Reference Handler] (Suspended)
Object.wait(long) line: not available [native method]
Reference$Lock(Object).wait() line: 485
Reference$ReferenceHandler.run() line: not available
Thread [AWT-Shutdown] (Suspended)
Object.wait(long) line: not available [native method]
Object.wait() line: 485
AWTAutoShutdown.run() line: not available
Thread.run() line: not available
Daemon System Thread [Java2D Disposer] (Suspended)
Object.wait(long) line: not available [native method]
ReferenceQueue<T>.remove(long) line: not available
ReferenceQueue<T>.remove() line: not available
Disposer.run() line: not available
Thread.run() line: not available
Daemon Thread [AWT-Windows] (Suspended)
WToolkit.eventLoop() line: not available [native method]
WToolkit.run() line: not available
Thread.run() line: not available
Thread [AWT-EventQueue-0] (Suspended)
EventQueue.removeSourceEvents(Object, boolean) line: not available
WindowsComboBoxUI$WindowsComboBoxRenderer(Component).removeNotify() line: not available
WindowsComboBoxUI$WindowsComboBoxRenderer(Container).removeNotify() line: not available
WindowsComboBoxUI$WindowsComboBoxRenderer(JComponent).removeNotify() line: not available
CellRendererPane(Container).remove(int) line: not available
CellRendererPane(Container).remove(Component) line: not available
WindowsComboBoxUI(BasicComboBoxUI).getSizeForComponent(Component) line: not available
WindowsComboBoxUI(BasicComboBoxUI).getDisplaySize() line: not available
WindowsComboBoxUI(BasicComboBoxUI).getMinimumSize(JComponent) line: not available
AutoCompleteComboBox(JComponent).getMinimumSize() line: not available
FlowLayout.minimumLayoutSize(Container) line: not available
JPanel(Container).minimumSize() line: not available
JPanel(Container).getMinimumSize() line: not available
JPanel(JComponent).getMinimumSize() line: not available
BoxLayout.checkRequests() line: not available
BoxLayout.minimumLayoutSize(Container) line: not available
JPanel(Container).minimumSize() line: not available
JPanel(Container).getMinimumSize() line: not available
JPanel(JComponent).getMinimumSize() line: not available
BoxLayout.checkRequests() line: not available
BoxLayout.preferredLayoutSize(Container) line: not available
JPanel(Container).preferredSize() line: not available
JPanel(Container).getPreferredSize() line: not available
JPanel(JComponent).getPreferredSize() line: not available
BorderLayout.layoutContainer(Container) line: not available
JPanel(Container).layout() line: not available
JPanel(Container).doLayout() line: not available
JPanel(Container).validateTree() line: not available
JPanel(Container).validateTree() line: not available
JPanel(Container).validateTree() line: not available
JLayeredPane(Container).validateTree() line: not available
JRootPane(Container).validateTree() line: not available
JRootPane(Container).validate() line: not available
RepaintManager.validateInvalidComponents() line: not available
SystemEventQueueUtilities$ComponentWorkRequest.run() line: not available
InvocationEvent.dispatch() line: not available
EventQueue.dispatchEvent(AWTEvent) line: not available
EventDispatchThread.pumpOneEventForFilters(int) line: not available
EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: not available
EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: not available
EventDispatchThread.pumpEvents(int, Conditional) line: not available
EventDispatchThread.pumpEvents(Conditional) line: not available
EventDispatchThread.run() line: not available
Thread [DestroyJavaVM] (Suspended)
Daemon System Thread [D3D Screen Updater] (Suspended)
Object.wait(long) line: not available [native method]
D3DScreenUpdateManager.run() line: not available
Thread.run() line: not available
Daemon System Thread [TimerQueue] (Suspended)
Object.wait(long) line: not available [native method]
TimerQueue.run() line: not available
Thread.run() line: not available
Thread [Thread-3] (Suspended)
Thread.sleep(long) line: not available [native method]
JDCConnectionPool$ConnectionReaper.run() line: 93
Daemon Thread [SwingWorker-pool-1-thread-1] (Suspended)
Unsafe.park(boolean, long) line: not available [native method]
LockSupport.park(Object) line: not available
AbstractQueuedSynchronizer$ConditionObject.await() line: not available
LinkedBlockingQueue<E>.take() line: not available
ThreadPoolExecutor.getTask() line: not available
ThreadPoolExecutor$Worker.run() line: not available
Thread.run() line: not available
Lot of thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
DB查询是在doInBackground()中完成的。
模型的更新需要在process()方法中完成。
有关详细信息,请阅读 Swing 教程中有关并发的部分。
The DB query is done in the doInBackground().
The updating of the model need to be done in the process() method.
Read the section from the Swing tutorial on Concurrency for more information.
向组合框中添加 100,000 个项目可能是问题的根源。
您还必须想知道一个用户如何能够处理组合框中的 100,000 个项目。
JComboBox
通常不应该处理如此大量的项目。优化代码的一种可能方法是显式调用
setPrototypeDisplayValue()
,这样,您就可以避免JComboBox
检查其所有模型项的尺寸来计算其自己的尺寸。这可能是您的系统看起来冻结的当前原因。Adding 100,000 items to your combo box is probably the root of your problem.
You also have to wonder how one user could possibly deal with 100,000 items in a combo box.
JComboBox
is normally not supposed to deal with such a big number of items.One possible way to optimize your code would be to explicitly call
setPrototypeDisplayValue()
, this way, you avoidJComboBox
checking the dimensions of ALL its model items to compute its own dimensions. That's probably the current reason why your system looks frozen.我知道您正在寻找带有大量建议的自动完成功能。
也许您可以查看 glazedlists 库。它的核心功能是提供可观察列表,但它非常灵活。您可以做的一件事是基于这样的列表构建 ComboBoxModel 并启用组合框的自动完成功能(通过 AutoCompleteSupport 类)。
此方法可以提供一种避免 addItem 中任何与 ComboBox 相关的性能问题的方法。该部分将被移至釉面列表中。
I understand you are looking for autocomplete functionality with a massive amount of suggestions.
Perhaps you can have a look at the glazedlists library. Its core function is to provide observable lists, but it is very flexible. One of the things you can do is build a ComboBoxModel based on such a list and enable autocompletion for a combobox (through the
AutoCompleteSupport
class).This approach may provide a way to avoid any ComboBox-related performance issues in addItem. That part would be moved into glazedlists.