Java 使用FormLayout批量重新绘制Swing组件
我正在做一个触摸屏键盘。我希望字母键在按下shift键(从小写到大写)时更改文本。以下是我当前实现的一个片段: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.
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;
}
}
}