Java 使用FormLayout批量重新绘制Swing组件

Java 使用FormLayout批量重新绘制Swing组件,java,swing,jbutton,form-layout,Java,Swing,Jbutton,Form Layout,我正在做一个触摸屏键盘。我希望字母键在按下shift键(从小写到大写)时更改文本。以下是我当前实现的一个片段: public void updatedButtons() { switch( m_state ) { case QWERTY: for( KeyboardButton button : m_keyboardButtons ) { button.setText( button.

我正在做一个触摸屏键盘。我希望字母键在按下shift键(从小写到大写)时更改文本。以下是我当前实现的一个片段:

public void updatedButtons()
{
    switch( m_state )
    {
        case QWERTY:
            for( KeyboardButton button : m_keyboardButtons )
            {
                button.setText( button.getQwertyText().toLowerCase() );
            }
            break;
        case QWERTY_SHIFT:
            for( KeyboardButton button : m_keyboardButtons )
            {
                button.setText( button.getQwertyText().toUpperCase() );
            }
            break;
    }
}
其中KeyboardButton是JButton的简单扩展,带有qwertyText字符串字段

这里的问题是按钮更新混乱。我明白为什么会这样;当我调用setText()时,它为单个组件调用repaint(),每个按钮都是这样。我的问题是,我是否能够在不破坏Swing设计的情况下“批量重新绘制”这些按钮(我不希望覆盖AbstractButton的setText()方法)。谢谢

更新

原来这是FormLayout的问题。下面是说明问题的简单代码(请注意,您将需要一个JGoodies表单Jar,并且可能需要修改断点值)

导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入com.jgoodies.forms.layout.CellConstraints;
导入com.jgoodies.forms.layout.FormLayout;
公共类JButtonTest
{
公共静态列表按钮=新建ArrayList();
公共静态布尔值isCaps=false;
公共静态JFrame;
公共静态void main(字符串[]args)
{
frame=新的JFrame();
框架设置尺寸(1000100);
JPanel面板=新的JPanel();
//具有11个83x83像素正方形的窗体,具有5x83像素空间。
panel.setLayout(新表单布局(“83px,5px,83px,5px,83px,5px,83px,5px,”
+“83px,5px,83px,5px,83px,5px,83px,5px,83px,5px,83px,5px,83px,5px,86px”,
“83px”);
int i=1;
for(字符c='a';c<'l';++c)
{
JButton button=新的ComplexButton(Character.toString(c));
addActionListener(新建ActionListener())
{
@凌驾
已执行的公共无效操作(操作事件e)
{
updateButtons();
}
});
添加(按钮,新建CellConstraints().xywh((i*2)-1,1,1,1,CellConstraints.FILL,CellConstraints.FILL));
按钮。添加(按钮);
++一,;
}
frame.setContentPane(面板);
frame.setVisible(true);
}
//在此方法中启用注释掉的行以允许并发更新。
公共静态void updateButtons()
{
用于(JButton按钮:按钮)
{
如果(!isCaps)
button.setText(button.getText().toUpperCase());
其他的
button.setText(button.getText().toLowerCase());
//repaitmanager.currentManager(按钮).markCompletelyClean(按钮);
}
//frame.repaint();
isCaps=!isCaps;
}
受保护的静态类ComplexButton扩展了JButton
{
公共ComplexButton(字符串)
{
超级(字符串);
}
@凌驾
公共空间涂料(图g)
{
int断点=3000000;
超级油漆(g);
//模拟一些复杂的操作。
对于(int i=0;i
请注意,如果您从FormLayout更改为FlowLayout,那么它工作得非常好(尽管本质上很慢)。如果您删除注释代码上的注释,它也可以正常工作(感谢程序员)

还要注意的是,如果将printlns放在updateButtons()方法的开头和结尾,该方法将在按钮停止更新之前很久结束,并且按钮不会同步更新。这意味着在FormLayout中,重新绘制的合并特性在某种程度上没有得到保留


不管怎样,即使它被保留下来,迟钝的控件和无序更新的控件一样糟糕。我想我必须尝试优化我们的绘制代码。感谢您的支持。

Swing中的绘制由
重新绘制管理器控制,该管理器决定何时更新内容。
repaitmanager
经过优化,以减少其计划的绘制事件数,从而保持性能

这意味着,当它接收到一系列重绘请求时,它将把它们合并为尽可能少的绘制事件。这意味着,当您在一组按钮上从循环内调用
setText
时,
repaitmanager
很可能已将其减少到尽可能接近一个(取决于您正在更新的内容,可能会有更多,但很可能会少于循环的迭代次数)

例如,它似乎对我有用

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestKeyboard {

    public static void main(String[] args) {
        new TestKeyboard();
    }

    public TestKeyboard() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<JButton> buttons;

        public TestPane() {
            setFocusable(true);
            setLayout(new GridLayout(0, 4));
            buttons = new ArrayList<>(26);
            for (int index = 0; index < 26; index++) {
                JButton btn = createButton(index);
                buttons.add(btn);
                add(btn);
            }

            addKeyListener(new KeyAdapter() {

                @Override
                public void keyPressed(KeyEvent e) {
                    if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
                        for (JButton btn : buttons) {
                            String text = btn.getText().toUpperCase();
                            btn.setText(text);
                        }
                        revalidate();
                        repaint();
                    }
                }

                @Override
                public void keyReleased(KeyEvent e) {
                    if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
                        for (JButton btn : buttons) {
                            String text = btn.getText().toLowerCase();
                            btn.setText(text);
                        }
                        revalidate();
                        repaint();
                    }
                }               
            });
        }

        protected JButton createButton(int index) {
            JButton btn = new JButton(Character.toString((char) ('a' + index)));
            btn.setMargin(new Insets(4, 4, 4, 4));
            btn.setFocusable(false);
            btn.setFocusPainted(false);
            return btn;
        }

    }

}

导入java.awt.EventQueue;
导入java.awt.GridLayout;
导入java.awt.Insets;
导入java.awt.event.KeyAdapter;
导入java.awt.event.KeyEvent;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公共类测试键盘{
公共静态void main(字符串[]args){
新的测试键盘();
}
公共测试键盘(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JFrame=newj
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestKeyboard {

    public static void main(String[] args) {
        new TestKeyboard();
    }

    public TestKeyboard() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<JButton> buttons;

        public TestPane() {
            setFocusable(true);
            setLayout(new GridLayout(0, 4));
            buttons = new ArrayList<>(26);
            for (int index = 0; index < 26; index++) {
                JButton btn = createButton(index);
                buttons.add(btn);
                add(btn);
            }

            addKeyListener(new KeyAdapter() {

                @Override
                public void keyPressed(KeyEvent e) {
                    if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
                        for (JButton btn : buttons) {
                            String text = btn.getText().toUpperCase();
                            btn.setText(text);
                        }
                        revalidate();
                        repaint();
                    }
                }

                @Override
                public void keyReleased(KeyEvent e) {
                    if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
                        for (JButton btn : buttons) {
                            String text = btn.getText().toLowerCase();
                            btn.setText(text);
                        }
                        revalidate();
                        repaint();
                    }
                }               
            });
        }

        protected JButton createButton(int index) {
            JButton btn = new JButton(Character.toString((char) ('a' + index)));
            btn.setMargin(new Insets(4, 4, 4, 4));
            btn.setFocusable(false);
            btn.setFocusPainted(false);
            return btn;
        }

    }

}