Swing开发界面时的一个bug复盘

简介: 问题:QA突然发个截图说一个Dialog上展示的东西变形了 分析:不理解,什么也没做,怎么会变形,刚刚我用的时候还正常。看看代码,的确什么也没更改;在本地测一下,也没有问题;baidu,bing,stackoverflow下,没找到什么线索突然看到一个ComboBox下面有一个item的值比较长, 布局使用的是GridBagLayout,也就是相对布局,如果设置Size是固定的,如果有一个控件变大,则整体的布局变形了 因此这个Combobox item的值比较长解决了,这个问题就解决了。

 

问题:
QA突然发个截图说一个Dialog上展示的东西变形了

分析:
不理解,什么也没做,怎么会变形,刚刚我用的时候还正常。
看看代码,的确什么也没更改;
在本地测一下,也没有问题;
baidu,bing,stackoverflow下,没找到什么线索

突然看到一个ComboBox下面有一个item的值比较长,

布局使用的是GridBagLayout,也就是相对布局,如果设置Size是固定的,如果有一个控件变大,则整体的布局变形了

因此这个Combobox item的值比较长解决了,这个问题就解决了。

解决的思路:
如果JComboBox列表中的内容过长的话,下拉框中不全部显示
解决方法一:当鼠标放在这个过长的项目中时显示tooltip,提示用户选择这项的全部信息
解决方法二:获取最大长项目宽度,并设置为弹出下拉框时的宽度
http://blog.chinaunix.net/uid-12888785-id-2384254.html

最终采用的是方法一,重写JcomboBox,里面存在两个Map,map1<model-element,displayName>,map2<model-element,displayName4ToolTextTip>
分为三种数据:Model,displayName,toolTextTip

复盘:
如果出现bug,找问题原因要了解场景,出bug时要了解问题前和问题后的差异,
有差异时,就找是否由差异引起的,
没有差异时,就确定是否是隐藏的bug:由于某些值超过Threshold,要查看出bug前的值和bug后的值有什么不同,缩小查找bug的范围

(1)更改引起bug
(2)某些值的改变引起bug

 
重写的JComboBox:

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;

public class JComboBox4ItemWidth extends JComboBox {
    private static final long serialVersionUID = 1L;

    private Map<String, String> antFactory_value_displayName4toolTipText;
    private Map<String, String> antFactory_value_displayName4dispaly = new HashMap<String, String>();

    public JComboBox4ItemWidth() {

        this.setRenderer(new ListCellRendererImpl());
        this.addItemListener(new ItemListenerImpl());
        this.setBackground(Color.WHITE);
    }

    public void setModelData(Object antFactory_value_displayName) {
        this.antFactory_value_displayName4toolTipText = (Map<String, String>) antFactory_value_displayName;
        Set<Entry<String, String>> antFactorys = this.antFactory_value_displayName4toolTipText.entrySet();
        DefaultComboBoxModel model = new DefaultComboBoxModel();

        for (Entry<String, String> antFactory : antFactorys) {
            antFactory_value_displayName4dispaly.put(antFactory.getKey(), format(antFactory.getValue()));
            model.addElement(antFactory.getKey());
        }
        this.setModel(model);

    }

    private String format(String displayValue) {
        if (displayValue.length() > 9) {
            displayValue = displayValue.substring(0, 6) + "...";
        }
        return displayValue;
    }

    public void setMoValue(Object value) {
        if (value != null && value.toString().trim().length() > 0) {
            this.setSelectedItem(value.toString());
            this.setToolTipText(getToolTipText4Display(value));
        } else {
            this.setSelectedIndex(-1); // 若从服务端得到的值是空,则界面显示空
            this.setToolTipText("");
        }
    }

    public Object getMoValue() {
        Object value = this.getSelectedItem();
        if (value != null && value.toString().trim().length() == 0) {
            value = "";
        }
        return value;
    }

    public String getDisplayValue(Object antFacotryValue) {
        String displayValue = this.antFactory_value_displayName4dispaly.get((String) antFacotryValue);
        return displayValue == null ? " " : displayValue;// 为空是需要空格,下拉选项才可显示出空值选项
    }

    public String getToolTipText4Display(Object antFacotryValue) {
        String displayValue = this.antFactory_value_displayName4toolTipText.get(antFacotryValue.toString());
        return displayValue == null ? " " : displayValue;// 为空是需要空格,下拉选项才可显示出空值选项
    }

    class ListCellRendererImpl extends DefaultListCellRenderer {
        private static final long serialVersionUID = -6671159080681655776L;

        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            String display = getDisplayValue(value);
            JComponent comp = (JComponent) super.getListCellRendererComponent(list, display, index, isSelected, cellHasFocus);
            comp.setToolTipText(getToolTipText4Display(value));
            return comp;
        }
    }

    class ItemListenerImpl implements ItemListener {
        @Override
        public void itemStateChanged(ItemEvent e) {
            setToolTipText(getToolTipText4Display(getSelectedItem()));
        }
    }

}

 




相关文章
|
存储 Linux 图形学
Unity 基础 之 PlayerPrefs数据存储
PlayerPrefs 游戏存档俗称玩家偏好。 工作原理非常简单,以键值对的形式将数据保存在文件中,然后程序可以根据这个名称取出上次保存的数值。
955 0
|
12月前
|
数据采集 人工智能 运维
云应用开发平台CAP
云应用开发平台CAP
|
算法 机器人 Unix
代码背后的女性:突破性别壁垒的技术先驱
代码背后的女性:突破性别壁垒的技术先驱
395 1
|
前端开发 开发者
对比state和props的区别?
对比state和props的区别?
|
12月前
|
存储 C语言
【c语言】数据类型和变量
本文介绍了C语言中的数据类型和变量。数据类型分为内置类型和自定义类型,内置类型包括字符型、整型、浮点型等,每种类型有不同的内存大小和取值范围。变量分为全局变量和局部变量,它们在内存中的存储位置也有所不同,分别位于静态区和栈区。通过示例代码和图解,详细阐述了这些概念及其应用。
222 1
|
存储 C语言 C++
C++中STL常用容器(vector、deque、list、map、set)一文带你了解
C++中STL常用容器(vector、deque、list、map、set)一文带你了解
473 0
|
机器学习/深度学习 人工智能 自动驾驶
强化学习算法在游戏、机器人和自动驾驶等领域的应用与实践
强化学习算法在游戏、机器人和自动驾驶等领域的应用与实践
681 0
强化学习算法在游戏、机器人和自动驾驶等领域的应用与实践
|
机器学习/深度学习 人工智能 算法
AI大模型“卷”到了旅游业?
沉寂许久的旅游行业再度活跃起来,迎来了新的增长。
447 0
|
弹性计算 人工智能 负载均衡
什么是阿里云服务器?云服务器的优缺点
阿里云是阿里巴巴集团的旗舰云计算品牌,它为全球各种规模的企业提供了云计算服务。阿里云服务器是阿里云的一项核心业务,它是一种可靠的云服务解决方案,具有许多优势。
931 0
|
机器学习/深度学习 人工智能 自然语言处理
基于 R 语言的深度学习——简介及资料分享
基于 R 语言的深度学习——简介及资料分享
468 0