加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 在运行时创建swing组件

发布时间:2020-12-14 19:23:23 所属栏目:Java 来源:网络整理
导读:我创建了应用程序,它的表现非常符合预期. 只要数据库查询正在运行,gui就会保持响应. 使用SwingUtilities.invokeLater()创建自定义面板时,gui会冻结很短的时间. 当我使用SwingUtilities.invokeAndWait()时,它在高端游戏PC上运行非常流畅. (可能不是最好的代码

我创建了应用程序,它的表现非常符合预期.
只要数据库查询正在运行,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 
            SwingWorker

我想我应该使用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组件.

如果结果集包含很多行,那么使用这种方法可能会在创建自定义面板时冻结gui.

什么是最优雅的方法来解决或最小化这个问题?

最佳答案
您应该考虑限制首先显示的结果数量!

除此之外,Swing组件创建非常有效.事实上,我希望它能够像结果从数据库中返回的那样快速地创建离屏组件实例,如果不是更快的话.你确定这真的是瓶颈吗?

最后,如果您担心冻结,您可以随时使用invokeLater为每个自定义面板启动单独的事件.然后,在每个面板创建之间将有机会进行事件处理,这应该消除“冻结”效果.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读