使用JPopupMenu + JTextField进行快速搜索 [英] Using JPopupMenu + JTextField for a quick search
问题描述
我有一个显示业务数据的JTable
.为了使它更有用,我想在右键单击列标题时添加一个弹出菜单,该标题仅显示一个文本输入字段,用作过滤的输入.
I have a JTable
that displays business data. To make it more usable, I want to add a popup menu when right-clicking the column header which simply displays a text input field which serves as the input for a filtering.
在列标题上单击鼠标右键并在其中添加JTextField
时,很容易添加一个弹出菜单.但是,我希望文本字段自动获得焦点,以便用户可以立即开始键入,而不必首先聚焦文本字段.
It's easy to add a popup menu when right-clicking on the column header and to put a JTextField
inside it. However, I would like the text field to automatically gain focus so that the user can instantly start typing rather than having to focus the text field first.
相关代码(在下面可以正常使用的SSCCE):
final JTextField filter = new JTextField( 20 );
final JPopupMenu popup = new JPopupMenu();
popup.add( filter );
table.getTableHeader().addMouseListener( new MouseAdapter() {
@Override
public void mousePressed( MouseEvent event ) {
if( !event.isPopupTrigger() ) {
return;
}
popup.show( table, event.getX(), event.getY() );
// TODO focus the text field
}
} );
在TODO
注释的位置,我尝试了类似filter.requestFocusInWindow()
的操作,但这不起作用.我认为弹出菜单本身正在夺走焦点.触发弹出窗口时,如何强制文本字段获得焦点?
At the TODO
comment's location I tried things like filter.requestFocusInWindow()
, but that doesn't work. I assume that the popup menu itself is stealing the focus. How can I force the text field to gain focus when the popup is triggered?
或者,如果有更好的方法来显示文本字段弹出窗口,我也很高兴看到它:)
Alternatively if there is a better way to display a text field popup I'd be glad to see that, too :)
SSCCE:
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
public class Test {
private static final JTable table = new JTable( new Object[][] {
{ "Foo", "Bar" }
}, new Object[] {
"A", "B"
} );
public static void main( String[] args ) {
final JTextField filter = new JTextField( 20 );
final JPopupMenu popup = new JPopupMenu();
popup.add( filter );
table.getTableHeader().addMouseListener( new MouseAdapter() {
@Override
public void mousePressed( MouseEvent event ) {
if( !event.isPopupTrigger() ) {
return;
}
popup.show( table, event.getX(), event.getY() );
// TODO focus the text field
}
} );
JFrame frame = new JFrame();
frame.add( new JScrollPane( table ) );
frame.pack();
frame.setVisible( true );
}
}
推荐答案
我使用JOptionPane.showInputDialog()使它工作,但这只是……不舒服.我真的很想弹出一个快捷文本字段.
I get it to work using JOptionPane.showInputDialog(), but that's just… uncomfortable. I'd really like having a quick&easy text field popping up.
不要尝试使用JPopupMenu
来实现它,而要使用未修饰的JDialog
来实现.它稍微灵活一些,但是需要您说出何时不再需要它,这与JPopupMenu
不同.后者并不是真的打算容纳文本字段.
Instead of trying to implement this using JPopupMenu
, do it with an undecorated JDialog
. It's somewhat more flexible but requires you to say when it is no longer needed, unlike a JPopupMenu
. The latter isn't really intended to house text fields.
import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class Test extends JFrame {
public Test() {
final JTable table = new JTable(new Object[][]{
{"Foo", "Bar"}
}, new Object[]{
"A", "B"
});
final JTextField filter = new JTextField(20);
final JDialog dialog = new JDialog(this);
dialog.setLayout(new BorderLayout());
dialog.setUndecorated(true);
dialog.add(filter);
dialog.pack();
Action hideAction = new HideAction(dialog);
ActionMap actionMap = filter.getActionMap();
InputMap inputMap = filter.getInputMap(JComponent.WHEN_FOCUSED);
actionMap.put("hideAction", hideAction);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "hideAction");
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "hideAction");
filter.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
dialog.setVisible(false);
}
});
table.getTableHeader().addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent event) {
if (!event.isPopupTrigger()) {
return;
}
showDialog(event);
}
@Override
public void mouseReleased(MouseEvent event) {
if (!event.isPopupTrigger()) {
return;
}
showDialog(event);
}
private void showDialog(MouseEvent event) {
Point convertedPoint = SwingUtilities.convertPoint(
table.getTableHeader(), event.getPoint(), Test.this);
Point locationOnScreen = Test.this.getLocationOnScreen();
locationOnScreen.translate(convertedPoint.x, convertedPoint.y);
dialog.setLocation(locationOnScreen);
dialog.setVisible(true);
// do whatever
}
});
add(new JScrollPane(table));
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Test frame = new Test();
frame.setVisible(true);
}
});
}
private static class HideAction extends AbstractAction {
final JDialog target;
public HideAction(JDialog target) {
this.target = target;
}
public void actionPerformed(ActionEvent e) {
target.setVisible(false);
}
}
}
六个月后,如果您仍然在寻找答案,就可以了.是的,我很无聊.
这篇关于使用JPopupMenu + JTextField进行快速搜索的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!