可以显示横向ScrollBar的下拉框ComboBox

本文介绍了一种通过自定义Swing组件的方式扩展下拉框的功能,包括改变UI外观及实现横向滚动条显示的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个不知道有没有人写过.
有点限制, 因为替换了UI, 所以只能在Metal下看才不会有异样的感觉.
import java.awt.Dimension;
import java.util.Vector;
import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;
/**
 * Created at 2006-7-25 13:06:10<br>
 * 下拉延长的下拉框
 
*/

@SuppressWarnings(
"serial")
public class ExtendedComboBox extends JComboBox {
 
public ExtendedComboBox() {
 }

 
/**
  * 
@param aModel
  
*/

 
public ExtendedComboBox(ComboBoxModel aModel) {
  
super(aModel);
 }

 
/**
  * 
@param items
  
*/

 
public ExtendedComboBox(Object[] items) {
  
super(items);
 }

 
/**
  * 
@param items
  
*/

 
public ExtendedComboBox(Vector<?> items) {
  
super(items);
 }

 
/**
  * (非 Javadoc)
  *
  * 
@see javax.swing.JComboBox#updateUI()
  
*/

 @Override
 
public void updateUI() {
  setUI(
new ExtendedComboBoxUI());
 }

 
/**
  * (非 Javadoc)<br>
  * 如果需要修改最适合尺寸, 重写此方法
  *
  * 
@see javax.swing.JComponent#getPreferredSize()
  
*/

 @Override
 
public Dimension getPreferredSize() {
  Dimension dim 
= super.getPreferredSize();
  dim.width 
= 120;
  
return dim;
 }

}

 
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.plaf.metal.MetalComboBoxUI;
/**
 * Created at 2006-7-25 13:09:13<br>
 * 延长的ComboBoxUI
 
*/

public class ExtendedComboBoxUI extends MetalComboBoxUI {
 
public static ComponentUI createUI(JComponent c) {
  
return new ExtendedComboBoxUI();
 }

 
/**
  * (非 Javadoc)
  *
  * 
@see javax.swing.plaf.basic.BasicComboBoxUI#createPopup()
  
*/

 
protected ComboPopup createPopup() {
  ExtendedComboPopup popup 
= new ExtendedComboPopup(comboBox);
  popup.getAccessibleContext().setAccessibleParent(comboBox);
  
return popup;
 }

 
public ComboPopup getPopup() {
  
return popup;
 }

}

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Rectangle;
import javax.swing.JComboBox;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ScrollPaneConstants;
import javax.swing.plaf.basic.BasicComboPopup;
/**
 * Created at 2006-7-25 13:07:04<br>
 * 延长的下拉框弹出菜单
 
*/

@SuppressWarnings(
"serial")
public class ExtendedComboPopup extends BasicComboPopup {
 
private int width = -1;
 
private int maxWidth = 300;
 
/**
  * 
@param combo
  
*/

 
public ExtendedComboPopup(JComboBox combo) {
  
super(combo);
 }

 
/**
  * (非 Javadoc)
  *
  * 
@see javax.swing.plaf.basic.BasicComboPopup#createScroller()
  
*/

 
protected JScrollPane createScroller() {
  
return new JScrollPane(list, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
    ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
 }

 
/**
  * (非 Javadoc)
  *
  * 
@see java.awt.Component#show()
  
*/

 @SuppressWarnings(
"deprecation")
 
public void show() {
  
// todo: if not set the width of popup menu,
  
// then set the default width(width of combobox)
  Dimension popupSize = comboBox.getSize();
  Insets insets 
= getInsets();
  popupSize.setSize(popupSize.width 
- (insets.right + insets.left),
    getPopupHeightForRowCount(comboBox.getMaximumRowCount()));
  
// 计算最大项目的宽度
  int maxWidthOfCell = calcPreferredWidth();
  width 
= maxWidthOfCell;
  
if (width > this.maxWidth)
   width 
= this.maxWidth;
  
if (width < this.comboBox.getWidth())
   width 
= comboBox.getWidth();
  
if (maxWidthOfCell > width) {
   
// 显示竖滚动条
   
// 需要增加高度
   popupSize.height += scroller.getHorizontalScrollBar().getPreferredSize().height;
  }

  Rectangle popupBounds 
= computePopupBounds(0, comboBox.getBounds().height, width,
    popupSize.height);
  scroller.setMaximumSize(popupBounds.getSize());
  scroller.setPreferredSize(popupBounds.getSize());
  scroller.setMinimumSize(popupBounds.getSize());
  list.invalidate();
  syncListSelectionWithComboBoxSelection();
  list.ensureIndexIsVisible(list.getSelectedIndex());
  setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled());
  show(comboBox, popupBounds.x, popupBounds.y);
 }

 
/**
  * 计算当前的最适合宽度
  *
  * 
@return
  
*/

 
private int calcPreferredWidth() {
  
int width = 0;
  ListCellRenderer renderer 
= list.getCellRenderer();
  
for (int index = 0, count = list.getModel().getSize(); index < count; index++{
   Object element 
= list.getModel().getElementAt(index);
   Component comp 
= renderer.getListCellRendererComponent(list, element, index, false,
     
false);
   Dimension dim 
= comp.getPreferredSize();
   
if (dim.width > width)
    width 
= dim.width;
  }

  
return width;
 }

 
void syncListSelectionWithComboBoxSelection() {
  
int selectedIndex = comboBox.getSelectedIndex();
  
if (selectedIndex == -1{
   list.clearSelection();
  }
 else {
   list.setSelectedIndex(selectedIndex);
  }

 }

 
public void setPopupWidth(int width) {
  
this.width = width;
 }

}
其实重写UI的原因就是因为需要重写这个Popup. Java原先的Popup是不显示横向ScrollBar的. 而且更改了ScrollBar的显示原则以后, 那么尺寸也必须重新计算了.
 
### 关于 el-scrollbar 横向滚动条触屏支持 `el-scrollbar` 是 Element UI 和 Element Plus 提供的一个内置滚动条组件,虽然官方文档中并未详细说明其具体行为特性,但从其实现机制来看,该组件本质上依赖浏览器原生的滚动条逻辑来实现滚动效果。因此,在现代浏览器环境下,当设备具备触摸屏功能时,`el-scrollbar` 的横向滚动条通常能够响应触控手势并正常工作。 然而需要注意的是,某些情况下可能由于 CSS 样式配置不当或者父级容器布局限制,导致触屏操作无法触发预期的行为。例如: - 如果 `overflow-x` 被显式设置为 `hidden` 或者其他值,则可能会禁用横向滚动[^3]。 - 若存在嵌套滚动容器(如 `el-tabs` 中使用了 `el-scrollbar`),则需确保子容器宽度正确计算以允许内容溢出[^5]。 为了验证 `el-scrollbar` 是否在特定场景下支持触屏滑动,可以尝试以下方法测试或调整代码: #### 测试与优化建议 1. **确认基础环境** 确保当前使用的框架版本兼容目标平台,并开启开发者工具模拟移动设备模式进行调试。 2. **检查样式冲突** 审查是否有自定义样式干扰了正常的滚动交互体验。如果发现异常情况可以通过覆盖原有规则修复问题: ```css /* 强制启用水平方向上的可滚动状态 */ .el-scrollbar__wrap { overflow-x: auto !important; } ``` 3. **增强用户体验** 对于移动端应用来说,除了基本的功能外还可以考虑加入惯性动画等高级特性提升手感质量。下面是一个简单的例子演示如何监听手指动作从而动态更新视图位置: ```javascript const handleTouchMove = (e) => { e.preventDefault(); // 取消默认事件防止页面整体位移 let deltaX = initialX - e.touches[0].clientX; // 计算偏移量 scrollWrapper.scrollLeft += deltaX * sensitivityFactor; // 更新scrollLeft属性值 initialX = e.touches[0].clientX; // 更新起始坐标用于下次增量运算 }; ``` 综上所述,尽管没有直接提及关于触屏的支持细节,但由于遵循标准DOM模型构建而成的缘故,默认情形之下应当是可以满足需求的。不过实际运用过程中仍需留意各种潜在因素的影响范围以便及时作出相应处理措施[^1][^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值