gpt4 book ai didi

java - JComboBox 和 JTable 作为 ListCellRenderer 组件

转载 作者:行者123 更新时间:2023-11-30 10:29:55 25 4
gpt4 key购买 nike

我目前正在开发一个 JComboBox 组件,我希望在 ComboBox 中有一个 JTable 用于下拉选择。我已经扩展了 ListCellRenderer 并且我在弹出窗口中有表格。

我想用两种不同的方式来呈现它。当弹出窗口不可见时,第一个作为所选行的绑定(bind)列的标签。第二个是在弹出窗口可见时使用 JScrollPane 显示表格。

不幸的是,当我这样做时,弹出窗口被缩小到列表的行高,只为表格的列留出空间。

如果我只使用滚动 Pane ,我可以看到完整的表格,但是当弹出窗口不可见时,我会看到组合框内的表格,这不是我想要的。

如何设置高度,使表格可以适应,同时仍然能够仅在弹出窗口不可见时显示标签?

下面是一个编译和运行的最小示例:

import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;

public class TableComboBoxMain {
public static void main(String[] args) {
JTableComboBox<Employee> combo = new JTableComboBox<>();
combo.addItem(new Employee("April",3));
//combo.setMaximumRowCount(10);
combo.setRenderer(new TableListCellRenderer(combo));
JFrame frame = new JFrame("Test Table Combo Box");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(combo);
frame.pack();
frame.setVisible(true);
}

public static class Employee{
String name;
int nr;
public Employee(String name, int number ){
this.name =name;
this.nr = number;
}
}

public static class JTableComboBox<E> extends JComboBox<E> implements ListSelectionListener{
@Override
public void valueChanged(ListSelectionEvent e) {System.out.println("Row selected"+e.getFirstIndex());
this.setSelectedIndex(e.getFirstIndex());
}
}

public static class TableListCellRenderer extends JScrollPane implements ListCellRenderer{
JTable table;
JTableComboBox combo;
boolean mouseListenerAdded;
public TableListCellRenderer(JTableComboBox combo){
this.combo=combo;
DefaultTableModel model = new DefaultTableModel();
String[] cols1 = new String[]{"1","2","3","4"};
String[] cols2 = new String[]{"Mark","John","April","Mary"};
model.addColumn("Nr", cols1);model.addColumn("Name",cols2);
table = new JTable(model);table.setShowGrid(true);table.setGridColor(Color.gray);
this.getViewport().add(table);
}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if(!mouseListenerAdded){
list.addMouseListener(this.getListener());
mouseListenerAdded = true;
}//If this is uncommented then the BasicComboPopup size is always no more than 1 row?!!
if(!combo.isPopupVisible()){
Employee emp = (Employee) value;
return new JLabel(emp.name);

}else
return this;
}

public MouseAdapter getListener(){
MouseAdapter adapter = new MouseAdapter(){
@Override
public void mousePressed(MouseEvent e) {
if(combo.isPopupVisible()){
System.out.println("MouseClicked over list");
int row = table.rowAtPoint(e.getPoint());
if(row>0){
table.setRowSelectionInterval(row-1, row-1);
ListDataEvent event = new ListDataEvent(combo,ListDataEvent.CONTENTS_CHANGED,row-1,row-1);
combo.contentsChanged(event);
}
}
}
};
return adapter;
}
}
}

最佳答案

所以我找到了解决问题的方法。我还没有完成,因为我还想有一些互动:

  1. 我希望能够移动列
  2. 我希望能够为列提供弹出菜单
  3. 我希望能够用鼠标垂直滚动

我想发布解决方案,以防其他人想要一个起点示例。我将在解决这些附加问题时更新我的​​答案。

下面是测试类:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.table.DefaultTableModel;

public class TableComboBoxMain {
public static void main(String[] args) {
JTableComboBox<String> combo = new JTableComboBox<>();
combo.addItem("");
BasicComboBoxUI ui = new BasicComboBoxUI(){
@Override
protected ComboPopup createPopup() {
return new BasicComboPopup( comboBox ){
@Override
protected int getPopupHeightForRowCount(int maxRowCount) {
return 100;
}
@Override
protected JScrollPane createScroller() {
JScrollPane sp = new JScrollPane( list,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED );
sp.getHorizontalScrollBar().setFocusable( false );
return sp;
}
};
}
};
combo.setUI(ui);
combo.setRenderer(new TableListCellRenderer(combo));
JFrame frame = new JFrame("Test Table Combo Box");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(combo);
frame.pack();
frame.setVisible(true);
}

public static class Employee{
String name;
int nr;
public Employee(String name, int number ){
this.name =name;
this.nr = number;
}
}

public static class JTableComboBox<E> extends JComboBox<E> implements ListSelectionListener{
@Override
public void valueChanged(ListSelectionEvent e) {
System.out.println("Row selected"+e.getFirstIndex());
this.setSelectedIndex(e.getFirstIndex());
}
}

public static class TableListCellRenderer extends DefaultListCellRenderer{
JTable table;
JTableComboBox combo;
JPanel renderer = new JPanel();
JPanel colHeader = new JPanel();
JScrollPane scroll = new JScrollPane();
boolean mouseListenerAdded;
public TableListCellRenderer(JTableComboBox combo){
this.combo=combo;
DefaultTableModel model = new DefaultTableModel();
String[] cols1 = new String[]{"1","2","3","4","5","6"};
String[] cols2 = new String[]{"Mark","John","April","Mary","Joe","Jack"};
model.addColumn("Nr", cols1);model.addColumn("Name",cols2);
table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
colHeader.add(table.getTableHeader());
renderer.setLayout(new BorderLayout());
renderer.add(colHeader, BorderLayout.NORTH);
renderer.add(table,BorderLayout.CENTER);
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
scroll.getViewport().add(table);

}
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
list.setFixedCellHeight(table.getRowHeight()*(table.getRowCount()+1)+10);
list.setFixedCellWidth(table.getPreferredSize().width);
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if(!mouseListenerAdded){
list.addMouseListener(this.getListener());
mouseListenerAdded = true;
}
if(!combo.isPopupVisible()){
label.setText("Select...");
if(table.getSelectedRowCount()>0)
label.setText(""+table.getModel().getValueAt(table.getSelectedRow(),1));
return label;
}
return scroll;
}

public MouseAdapter getListener(){
MouseAdapter adapter = new MouseAdapter(){
@Override
public void mousePressed(MouseEvent e) {
if(combo.isPopupVisible()){
System.out.println("MouseClicked over list");
int row = table.rowAtPoint(e.getPoint());
if(row>0){
table.setRowSelectionInterval(row-1, row-1);
ListDataEvent event = new ListDataEvent(combo,ListDataEvent.CONTENTS_CHANGED,row-1,row-1);
combo.contentsChanged(event);
}
}
}
};
return adapter;
}
}
}

解决方案的关键部分是,为了在弹出窗口中显示表格和表格的功能,您需要覆盖 UI。具体来说,您需要覆盖 BasicComboBoxUI 上的 createPopupgetPopupHeightForRowCountBasicComboPopup 上的 createScroller .最后,在实现 getListCellRenderingComponent 时,您设置了一个固定的高度和宽度,以匹配表格的首选高度和宽度。这将允许弹出窗口的主滚动条充当表格的滚动 Pane 。

关于java - JComboBox 和 JTable 作为 ListCellRenderer 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43827658/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com