我创建了应用程序,它的表现非常符合预期.
只要数据库查询正在运行,gui就会保持响应.
使用SwingUtilities.invokeLater()创建自定义面板时,gui会冻结很短的时间.
当我使用SwingUtilities.invokeAndWait()时,它在高端游戏PC上运行非常流畅. (可能不是最好的代码机器……)
但在相对较慢的机器(双核,2GB RAM)上,gui“滞后”
我创建了一个非常小的程序版本来重现行为.
测试时增加TEST_NUMBER_OF_PANELS的值.
它将它设置为一个非常大的值,以重现我当前的电脑上的行为,没有任何花哨的外观和感觉和其他组件.但我不想这样张贴.
所以我减少到100
package test;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
//import org.pushingpixels.substance.api.SubstanceLookAndFeel;
//import org.pushingpixels.substance.api.skin.BusinessBlackSteelSkin;
//import org.pushingpixels.substance.api.skin.SubstanceBusinessBlackSteelLookAndFeel;
public class Test extends JFrame {
private static final int TEST_NUMBER_OF_PANELS = 100;
private static JTabbedPane tabbedPane = new JTabbedPane();
Test() {
this.setLayout(new BorderLayout());
this.setSize(1050,700);
this.setMinimumSize(new Dimension(400,200));
this.add(tabbedPane,BorderLayout.CENTER);
JButton testbutton = new JButton("new tab");
testbutton.addMouseListener(new MouseListener() {
@Override
public void mousePressed(MouseEvent e) {
tabbedPane.addTab("tab x",new TestTabContent());
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
this.add(testbutton,BorderLayout.NORTH);
//tabbedPane.addTab("tab1",new TestTabContent());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Test().setVisible(true);
/*
try {
UIManager.setLookAndFeel(new SubstanceBusinessBlackSteelLookAndFeel());
} catch (Exception e) {
System.out.println("Substance Business Failed to initialize");
}
SubstanceLookAndFeel.setSkin(new BusinessBlackSteelSkin());
new Test()
.setVisible(true);
*/
}
});
}
private class TestTabContent extends JPanel {
TestTabContent() {
final JPanel BoxContainer = new JPanel();
BoxContainer.setLayout(new BoxLayout(BoxContainer,BoxLayout.Y_AXIS));
JPanel BoxContainerOuter = new JPanel();
BoxContainerOuter.setLayout(new BorderLayout());
BoxContainerOuter.add(BoxContainer,BorderLayout.NORTH);
JScrollPane mainScrollPane = new JScrollPane(BoxContainerOuter);
// create toolbar
JPanel toolBar = new JPanel();
toolBar.setLayout(new BorderLayout());
//east
JPanel InfoPanel = new JPanel();
InfoPanel.setLayout(new BoxLayout(InfoPanel,BoxLayout.X_AXIS));
InfoPanel.add(new JLabel("test: some info ..."));
toolBar.add(InfoPanel,BorderLayout.WEST);
//west
JPanel viewOptionPanel = new JPanel();
viewOptionPanel.setLayout(new BoxLayout(viewOptionPanel,BoxLayout.X_AXIS));
viewOptionPanel.add(new JLabel("some controls.."));
toolBar.add(viewOptionPanel,BorderLayout.EAST);
// set main panel´s layout
GroupLayout layout = new GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(toolBar,GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE)
.addComponent(mainScrollPane)
);
layout.setVerticalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(toolBar,GroupLayout.PREFERRED_SIZE,GroupLayout.PREFERRED_SIZE)
.addGap(0,0)
.addComponent(mainScrollPane,413,Short.MAX_VALUE))
);
// create controls
SwingWorkerBoxContainer.add(seperator);
}
});
}
return "";
}
};
worker.execute();
}
private ArrayListdioButtonWidth = 20;
private JTable table;
private DefaultTableModel tableModel;
private JPanel collapsiblePane;
private JButton collapsingButton;
TestPanel(ArrayListBoxLayout for collapsiblePane
JPanel BoxContainer = new JPanel();
BoxContainer.setLayout(new BoxLayout(BoxContainer,BoxLayout.Y_AXIS));
BoxContainer.setBorder(BorderFactory.createMatteBorder(0,1,Color.BLACK));
// set table stuff
tableModel = new DefaultTableModel();
tableModel.setColumnIdentifiers(
new Object[] {
"test","test","test"});
for (ArrayListBoxContainer.add(table.getTableHeader(),BorderLayout.NORTH);
BoxContainer.add(table,BorderLayout.CENTER);
// other controls / toolbar
JPanel toolbar = new JPanel();
toolbar.setLayout(new BorderLayout());
// buttons to the right
JPanel toolbarButtonGroup = new JPanel();
toolbarButtonGroup.setLayout(new BoxLayout(toolbarButtonGroup,BoxLayout.X_AXIS));
// test button
JButton button = new JButton("test");
JPanel sepPanel = new JPanel();
sepPanel.add(button);
toolbarButtonGroup.add(sepPanel);
// test button
button = new JButton("test");
sepPanel = new JPanel();
sepPanel.add(button);
toolbarButtonGroup.add(sepPanel);
// test button
button = new JButton("test");
sepPanel = new JPanel();
sepPanel.setBorder(BorderFactory.createEmptyBorder(0,5));
sepPanel.add(button);
toolbarButtonGroup.add(sepPanel);
toolbar.add(toolbarButtonGroup,BorderLayout.EAST);
BoxContainer.add(toolbar);
JPanel subPanel = new JPanel();
subPanel.setLayout(new BoxLayout(subPanel,BoxLayout.Y_AXIS));
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BorderLayout());
buttonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE,24));
collapsingButton = new JButton(tableModel.getValueAt(0,8).toString());
collapsingButton.setName("toggleButton");
collapsingButton.setHorizontalAlignment(SwingConstants.LEFT);
collapsingButton.setBorderPainted(false);
collapsingButton.setFocusPainted(false);
buttonPanel.add(collapsingButton,BorderLayout.CENTER);
buttonPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
subPanel.add(buttonPanel);
collapsiblePane = new JPanel();
collapsiblePane.setName("collapsiblePane");
collapsiblePane.setLayout(new CardLayout());
collapsiblePane.add(BoxContainer,"");
subPanel.add(collapsiblePane);
add(subPanel);
}
}
}
我想我应该使用SwingWorker而不是EDT运行尽可能多的代码.
我知道我应该在一个单独的线程中访问TableModel.
如果应用程序中只有一个JTable,那么它很简单:我在EDT上创建表并更新线程上的数据.
在那种情况下,我不确定哪种方法是可取的.
现在,所有与tabe相关的内容都在TestPanel类中进行管理.完全在EDT上运行.
当然我可以在TestPanel中运行一个线程来处理TableModel,但为每个面板创建一个新线程对我来说听起来不是一个聪明的主意.
另一个“想法”是在运行数据库查询的同一个线程上直接在TestTab中创建模型.
但由于它属于TestPanel,这种方法听起来像是糟糕的设计.
我迄今为止最脏的想法是使用invokeAndWait()并让Tread.sleep()暂停一段时间,这样ETD就不会每隔几毫秒被新的调用打耳光.
但我真的不想这样编码.
什么样的设计方法最合适?
我想在运行时在JTabbedPane中创建几个自定义面板.
自定义面板的数量取决于数据库查询的结果集.
每个自定义面板都包含一个JTable,其中包含来自结果集的一大块数据和一些JButton.
我的计划是使用SwingWorker在单独的线程上运行数据库查询.
然后使用invokeLater()在Event Dispatch Thread上安排任务以创建自定义面板,因为必须在EDT中创建和访问swing组件.